In fact, more recently in this article, "iOS Tutorial: Using persistent Data" core data, this is the "iOS Development tutorial: Storyboard Full resolution-Part One" of the follow-up, but it is not completed, first released a persistent data storage tutorial for reference. This is actually a translation of the article, in the original English see here. I have changed some of the content in order to adapt to the tastes of our Chinese, please see the tutorial below:
As I've always said, core data is the best way to use persistent data storage for iOS programming and even Mac programming, and core data essentially uses SQLite, but with a series of features that avoids the hassle of using some of the columns of SQL, He is also able to reasonably manage the memory, anyway the benefits are many, we recommend to use.
In this tutorial, we will create a visual model of core data and then make a table view so that the contents of the table view can be stored in the data model.
Create a Core Data project
First open Xcode, create a new project, and select the Master-detail template.
We use FAILEDBANKCD as the project name here.
Remember to select Use storyboards, use Core Data, and use Automatic Reference counting These options, and then create.
Before I start, I want to remove some unused template files and select four files.
- FBCDMasterViewController.h
- Fbcdmasterviewcontroller.m
- FBCDDetailViewController.h
- Fbcddetailviewcontroller.m
Delete it, solve everything, select "Move to Trash".
Now use Obj-c class template to create a new file, named Fbcdmasterviewcontroller He is a uitableviewcontroller, remember that the following few hooks are not selectable.
Select FBCDMasterViewController.h to add code to the end line before @end:
@property (Nonatomic,strong) nsmanagedobjectcontext* managedobjectcontext; |
Now come to the. m file and add the following statement.
@synthesize Managedobjectcontext; |
If you don't know what "Nsmanagedobjectcontext" is, it's okay, we'll talk about it later.
But we're going to have to remove the view of the class that we just deleted in the storyboard, see figure:
Finally, with Failedbankscd.xcdatamodel selected, you'll see a visual editor coming up. We will then use this editor to edit our data model, select the middle display "entity" bubble, and then delete it.
If your editor looks different from the one below, change the editor style to Visual view
OK, done, if you start the app now, you'll find that he's a blank app.
Open the FAILEDBANKSCDAPPDELEGATE.M and you'll see that there are already some pre-built functions here, which is to build the stack of core data, including how to create a data model, how to manage the data model, how to build a persistent data coordinator, and so on.
If these terms look at you headache, it doesn't matter, read the following explanation you will understand:
- Managed Object Model (Management data Model): You can look at this thing as a database outline, or structure. This contains the definition information for each entity, in general, you will use the visual editor we have just seen to manipulate the object, add attributes, establish relationships between attributes, and of course you can use the code.
- Persistent Store Coordinator (persistent data Coordinator): You can consider this as a database connection library, where you will set the name and location of the data store and the timing of the data storage.
- Managed Object Context (Managing Data content): You can think of this part as the actual content of the data, which is the most important part of the whole database for us (which is also said), basically, the work of inserting data, querying data, and deleting data is done here.
Now you don't have to know much about these methods, because we can't use them for the time being, but it's always good to know some concepts. Creating a data Model
Unlike SQLite, Core data is not able to extract certain attributes of an entity, you can only extract the entire entity, and then decompose them.
Let's see how this works, open the Visual editor (click Failedbankscd.xcodedatamode)
In the toolbar at the bottom, stand-alone plus, create a new entity.
After you create a new entity, the visual editor displays his properties
Name the new entity Failedbankinfo, and then stand on the entity to make sure that the third label of the visible part is selected. In the Third tab of the property inspector, you'll see that this entity is a subclass of Nsmanagedobject, which is the default class for the entity, which we'll use first, and we'll go back in the future to modify it to a custom class.
Now, let's add some properties (atrributes), make sure your entity is selected, then press the plus sign at the bottom of the middle panel, and a box like the one below will appear.
In the Data Model property Inspector, name this property "name" as shown below, with type set to "String"
Now, continue to add two new attribute "City" and "state", the type is a string.
Next, we create an entity named Failedbankdetails, you must have done it? After adding the following properties in the inside, the Zip (Integer32 property) closedate (Date property) Updatedate (Date property).
Finally, we connect the two entities, select Failedbankinfo, press and hold the middle panel's plus key, and select "Add relationship":
Name the relationship "Details" and set the target to "failedbankdetails."
Well, we've just set up a relationship that connects two entities, which means that each Failedbankinfo property will have a failedbankdetails entity, behind the set, the Core Data will automatically set the ID of the entity in Failedbankinfo, but we don't need to know that.
Apple's official recommendation is that every time you build a goal relationship, it's best to build a return relationship, so let's follow the official instructions.
In "Failedbankdetails" to establish a relationship called "info", set his goal is "Failedbankinfo", Just and "Details" this relationship is reversed.
Next, we set the delete rule for these two relationships to "cascade", which means that if you delete one of the data, the data in the other entity will be deleted along with this one.
Run it, what? The crash??
Oh, it turns out that a previously existing data cannot be read by our modified data model, in which case you just need to delete the app in the emulator and run it again.
Test our data Model
No matter what you think, testing is the most important step in our database editing.
First, we add some test data to our database, open FAILEDBANKSCDAPPDELEGATE.M, and add the following code to the top Application:didfinishlaunchingwithoptions method:
nsmanagedobjectcontext *context = [self managedobjectcontext]; Nsmanagedobject *failedbankinfo = [nsentitydescription insertnewobjectforentityforname:@ "FailedBankInfo" InManagedO Bjectcontext:context]; [Failedbankinfo setvalue:@ "Test Bank" forkey:@ "name"]; [Failedbankinfo setvalue:@ "Testville" forkey:@ "City"]; [Failedbankinfo setvalue:@ "Testland" forkey:@ "state"]; Nsmanagedobject *failedbankdetails = [nsentitydescription insertnewobjectforentityforname:@ "FailedBankDetails" InMa Nagedobjectcontext:context]; [Failedbankdetails setvalue:[nsdate Date] forkey:@ "closedate"]; [Failedbankdetails setvalue:[nsdate Date] forkey:@ "updatedate"]; [Failedbankdetails setvalue:[nsnumber numberwithint:12345] forkey:@ "zip"]; [Failedbankdetails setvalue:failedbankinfo forkey:@ "info"]; [Failedbankinfo setvalue:failedbankdetails forkey:@ "Details"]; Nserror *error;if (![ Context Save:&error]) {NSLog (@ "Whoops, couldn ' t Save:%@", [Error localizeddescription]);} |
In the first line, we created a pointer to our database.
Next, we create a nsmanagedobject entity for the Failedbankinfo entity, which uses the Insertnewobjectforname method, each using the core The way data is stored is derived from Nsmanagedobject, and when you create an instance of this method, you can assign values to any of the properties in the model that we just created in the visual editor.
Then we set up a test data, where the data is only modified in memory, and if we want to save the database, we must use the Managedobjectcontext method
Inserting a data is as simple as not using SQL statements at all.
Before we run, we'll use some code to list the data in our database.
Nsfetchrequest *fetchrequest = [[Nsfetchrequest alloc] init]; Nsentitydescription *entity = [nsentitydescription entityforname:@ "Failedbankinfo" Inmanagedobjectcontext: Context]; [Fetchrequest setentity:entity]; Nsarray *fetchedobjects = [Context executefetchrequest:fetchrequest error:&error];for (NSManagedObject *info In fetchedobjects) { NSLog (@ "Name:%@", [info valueforkey:@ "name"]); Nsmanagedobject *details = [info valueforkey:@ "Details"]; NSLog (@ "Zip:%@", [details valueforkey:@ "zip"]);} |
Here we create a new method called Fetch request, you can consider a fetch request as a SELECT statement in SQL, we call the Entityforname method to get a pointer to Failedbankinfo, Then use the Setentity method to tell us what kind of entity we want for the fetch request.
After that, we call the Executefetchrequest method, push all the data in the Failedbankinfo table into a data cache, enumerate all the Nsmanagedobject, and invoke the data in the Valueforkey statement.
Note that although we have all the data from the Failedbankinfo table, we can still access the Failedbankdetails data body through the detailed data in the Failedbankinfo entity.
Run this app, you can see nothing on the screen at the moment, you could look at the Program Output window, you can see the output, every time you set up the database should be done such a test.
Look at the true colors of SQL statements
I don't know what you think, but I personally like to see the SQL statements behind each statement to make sure that the program is moving in the way I want.
Apple provides an easy way to do this by selecting run in the edit scheme, then entering the arguments tag and adding the following statement: "-com.apple.coredata.sqldebug 1", when done, you will see the second picture:
Now, whenever you run this program, the debug bar will output the SQL statement of the active activity.
If you don't understand the SQL statement, it doesn't matter, no one is forcing you to learn this annoying thing, you can always use core Data.
Auto-generated model files
So far, we have been using Nsmanagedobject to deal with our entities, which is not the best way, why? Since Nsmanagedobject is not a strong class (strongly typed Class), you can only use strings to access data properties, which can cause errors if you make a mistake.
A better approach is to create a model file for each entity, which is a lot of benefit, not to repeat, and Xcode provides a class builder that makes it easy to do this task.
To try, open Failedbankscd.xcdatamodel, click failedbankinfo entity, enter File--newfile. Select the Core datansmanagedobject template, and then create:
You should see that some new files are added to your project, namely failedbankinfo.h/m and failedbankdetails.h/m, which are very simple classes just to declare the attributes you add to the entity. Xcode adds the statements dynamically and we don't have to worry about them.
Do the same thing for failedbankdetails entities.
But there's a problem with these auto-generated classes that we have to solve manually, If you open FailedBankDetails.h to see, you will find the info variable is declared failedbankinfo, but in FailedBankInfo.h, he was declared Nsmanagedobject class, in fact, it should be Failedbankdeta Ils class.
This is because the Failedbankinfo generator runs before the failedbankdetails generator, so the generator doesn't know that there's a thing behind it.
You can fix it manually like above, but there is an easy way to rerun the Failedbankinfo generator.
If we go back to Failedbankscd.xcdatamodel, when you look at the entities ' classes, you will find that they have been automatically modified to automatically create classes.
To test, open the bcdappdelegate.m and join in the head:
#import "FailedBankInfo.h" #import "FailedBankDetails.h" |
Then modify the code:
Nsmanagedobjectcontext *context = [self managedobjectcontext]; Failedbankinfo *failedbankinfo = [nsentitydescription insertnewobjectforentityforname:@ "FailedBankInfo" inManagedOb Jectcontext:context];failedbankinfo.name = @ "Test Bank"; failedbankinfo.city = @ "Testville"; failedbankinfo.state = @ " Testland "; Failedbankdetails *failedbankdetails = [nsentitydescription insertnewobjectforentityforname:@ "FailedBankDetails" in Managedobjectcontext:context];failedbankdetails.closedate = [NSDate date];failedbankdetails.updatedate = [NSDate Date];failedbankdetails.zip = [NSNumber numberwithint:12345];failedbankdetails.info = FailedBankInfo; Failedbankinfo.details = failedbankdetails; Nserror *error;if (![ Context Save:&error]) {NSLog (@ "Whoops, couldn ' t Save:%@", [Error localizeddescription]);} Test listing all Failedbankinfos from the storensfetchrequest *fetchrequest = [[Nsfetchrequest alloc] init]; Nsentitydescription *entity = [nsentitydescription entityforname:@ "FailedbankinFo "Inmanagedobjectcontext:context"; [Fetchrequest setentity:entity]; Nsarray *fetchedobjects = [Context executefetchrequest:fetchrequest error:&error];for (FailedBankInfo *info in fetchedobjects) {NSLog (@ "Name:%@", info.name); Failedbankdetails *details = info.details; NSLog (@ "ZIP:%@", details.zip);} |
That's the same code we tested last time, isn't it?
Create a table view
Open the FBCDMasterViewController.h declaration an array, you know (if you don't understand see how to create a simple table)
@property (nonatomic, strong) Nsarray *failedbankinfos; |
Please note that we have used some methods to get the data in the test, just in the Application:didfinishlaunchingwithoptions method in FBCDAPPDELEGATE.M, remember?
Return to FAILEDBANKSLISTVIEWCONTROLLER.M to make the following changes:
At very top, on import section#import "FailedBankInfo.h"//at top, under @implementation @synthesize Failedbankinfos; |
To modify the Viewdidload method:
-(void) viewdidload { [super viewdidload]; Nsfetchrequest *fetchrequest = [[Nsfetchrequest alloc] init]; Nsentitydescription *entity = [nsentitydescription entityforname:@ "Failedbankinfo" Inmanagedobjectcontext: Managedobjectcontext]; [Fetchrequest setentity:entity]; Nserror *error; Self.failedbankinfos = [Managedobjectcontext executefetchrequest:fetchrequest error:&error]; Self.title = @ "Failed Banks";} |
That's pretty much the code we're testing, isn't it? We use a FETCH request to get the data in the database and then store it in memory.
Numberofsectionsintableview:
-(Nsinteger) Numberofsectionsintableview: (UITableView *) TableView { return 1;} |
Numberofrowsinsection:
-(Nsinteger) TableView: (UITableView *) TableView numberofrowsinsection: (nsinteger) Section { return [ Failedbankinfos count];} |
Cellforrowatindexpath:
-(UITableViewCell *) TableView: (UITableView *) TableView cellforrowatindexpath: (Nsindexpath *) Indexpath { static NSString *cellidentifier = @ "Cell"; UITableViewCell *cell = [TableView dequeuereusablecellwithidentifier:cellidentifier]; Set up the cell ... Failedbankinfo *info = [Failedbankinfos objectAtIndex:indexPath.row]; Cell.textLabel.text = Info.name; Cell.detailTextLabel.text = [NSString stringwithformat:@ "%@,%@", info.city, info.state]; return cell;} |
The above is the code to make a table view, very familiar with it, next we make this table view in storyboard, remember to set the cell's style to subtitle.
Run the app and check it out.
What do you see later?
This is the example of my production process source code, welcome to download.
This is the original author's sample program: sample code for the project so far (direct download).
Please pay attention to my scarf: @Oratis
On the Oratis and the watercress, my name is the same.
I'll share the tutorials I've published later in these social networks.
If you have any questions, welcome to the bottom of the message, also welcome to write to me, my e-mail address is: [email protected]
iOS Tutorial: Core Data Persistence Storage Basics Tutorial