Ios data persistence-introduction and use of CoreData framework, ios-coredata
1. Core Data is the best way to store Data persistently.
2. The final data storage type can be: SQLite database, XML, binary, memory, or custom data type.
In Mac OS X 10.5Leopard and later versions, developers can also inherit the NSPersistentStore class to create custom storage formats.
3. Benefits: the memory can be properly managed to avoid the trouble and efficiency of using SQL.
4. Composition:
(1) NSManagedObjectContext (managed data context)
Actual Operation content (Operation persistence layer)
Purpose: insert data, query data, and delete data.
(2) NSManagedObjectModel (Managed Data Model)
All tables or data structures in the database, including definition information of each object
Purpose: Add attributes of an object to establish the relationship between attributes.
Operation Method: View editor or code
(3) NSPersistentStoreCoordinator (persistent Storage Assistant)
Connector equivalent to database
Purpose: set the data storage name, location, storage method, and storage time.
(4) NSManagedObject (Managed Data Records)
Equivalent to the table record in the database
(5) NSFetchRequest (request for data retrieval)
Equivalent to a query statement
(6) NSEntityDescription (entity structure)
Equivalent to table structure
(7) packages suffixed with. xcdatamodeld
It contains the. xcdatamodel file and is edited using the data model editor.
Compiled as a. momd or. mom file
5. Dependency
2. simple use of Core Data based on SQLite Databases
Difference from SQLite: only the entire entity record can be retrieved and then decomposed before a certain attribute of the object can be obtained.
1. Build Process
Including: creating a data context, creating a data model, and creating a data persistence Storage Assistant
(1) If a new project is created, select a blank application and click
Select Use Core Data
In the generated project file AppDelegate, the managed data context and other related code are automatically generated.
(2) For example, AppDelegate. H files are automatically generated.
@property (readonly, strong, nonatomic) NSManagedObjectContext *managedObjectContext;@property (readonly, strong, nonatomic) NSManagedObjectModel *managedObjectModel;@property (readonly, strong, nonatomic) NSPersistentStoreCoordinator *persistentStoreCoordinator; - (void)saveContext;- (NSURL *)applicationDocumentsDirectory;
Method saveContext: save data to the persistent layer (database)
Method applicationDocumentsDirectory: directory path of Documents under the application sandbox
(For example,/var/mobile/Applications/5FG80A45-DFB5-4087-A1B1-41342A977E21/Documents /)
(3) For example, AppDelegate. H files are automatically generated.
@synthesize managedObjectContext = __managedObjectContext;@synthesize managedObjectModel = __managedObjectModel;@synthesize persistentStoreCoordinator = __persistentStoreCoordinator;
Save data to the persistent layer
- (void)applicationWillTerminate:(UIApplication *)application{ [self saveContext];}
- (void)saveContext{ NSError *error = nil; NSManagedObjectContext *managedObjectContext = self.managedObjectContext; if (managedObjectContext != nil) { if ([managedObjectContext hasChanges] && ![managedObjectContext save:&error]) { NSLog(@"Unresolved error %@, %@", error, [error userInfo]); abort(); } }}
- (NSURL *)applicationDocumentsDirectory{ return [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];}
After initialization, you must set a persistent Storage Assistant
- (NSManagedObjectContext *)managedObjectContext{ if (__managedObjectContext != nil) { return __managedObjectContext; } NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator]; if (coordinator != nil) { __managedObjectContext = [[NSManagedObjectContext alloc] init]; [__managedObjectContext setPersistentStoreCoordinator:coordinator]; } return __managedObjectContext;}
Managed Data Model
The initialization must depend on the. momd file path, and the. momd file is compiled from the. xcdatamodeld file.
- (NSManagedObjectModel *)managedObjectModel{ if (__managedObjectModel != nil) { return __managedObjectModel; } NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"TestApp" withExtension:@"momd"]; __managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL]; return __managedObjectModel;}
Persistent Storage Assistant
The initialization must depend on NSManagedObjectModel, and then specify the Data Type of persistent storage. The default value is NSSQLiteStoreType, that is, SQLite database. The storage path is specified under the Documents directory and the database name.
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator{ if (__persistentStoreCoordinator != nil) { return __persistentStoreCoordinator; } NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"TestApp.sqlite"]; NSError *error = nil; __persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]]; if (![__persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:nil error:&error]) { NSLog(@"Unresolved error %@, %@", error, [error userInfo]); abort(); } return __persistentStoreCoordinator;}
If it is not a new project, you can write the relevant code yourself.
(4) The TestApp. xcdatamodeld file is also generated.
(5) The CoreData. framework is automatically linked.
(6) Add the header file CoreData. h to the pre-compiled header file.
# Import <CoreData/CoreData. h>
2. Create a data model (Data Model editor Operation)
(1) create an object
Select the. xcodedatamodel object
Click Add Entity in the bottom Toolbar of the data model editor on the right to Add an object.
Name an object in the rightmost column
(2) create Object Attributes
Select the object and click Add Attribute in the toolbar at the bottom to Add the Attribute.
Select the newly added Attribute, name the Attribute, and set the Attribute data Type.
(3) establish a relationship between two entities
Select an object and click Add Relationship in the toolbar at the bottom to Add a link.
Select a new link and add a name to the link. The destination is set to another object.
(4) Establish a return relationship
(When you establish a target relationship, it is best to establish a return relationship)
Create a link in another object and name it. Set the target object to the previous object.
Select the Link name before the Inverse attribute.
(5) set the Delete Rule for the two relationships to Delete the Rule. Both are associated modes.
Association mode cascade: One of the data is deleted, and the data in the other object is also deleted.
(6) The final relationship between the two objects is
Switch Editor Stype button
You can see another editing method:
3. insert data
In application: didfinishlaunchingwitexceptions: Method of AppDelegate. m, call the custom method.
InsertCoreData inserts data. The Code is as follows:
-(Void) insertCoreData {custom * context = [self managedObjectContext]; NSManagedObject * contactInfo = [NSEntityDescription metadata: @ "ContactInfo" metadata: context]; [contactInfo setValue: @ "name B" forKey: @ "name"]; [contactInfo setValue: @ "birthday B" forKey: @ "birthday"]; [contactInfo setValue: @ "age B" forKey: @ "age"]; NSManagedObject * contactDetai LInfo = [NSEntityDescription failed: @ "ContactDetailInfo" inManagedObjectContext: context]; [contactDetailInfo setValue: @ "address B" forKey: @ "address"]; [contactDetailInfo setValue: @ "name B" forKey: @ "name"]; [contactDetailInfo setValue: @ "telephone B" forKey: @ "telephone"]; [contactDetailInfo setValue: contactInfo forKey: @ "info"]; [contactInfo setValue: contactDetailInfo forKey: @ "Details"]; NSError * error; if (! [Context save: & error]) {NSLog (@ "cannot be saved: % @", [error localizedDescription]) ;}}
Create a data context, call the insertNewObjectForName method, create two data records NSManagedObject, and then assign values to the attributes defined in the previous data model editing view. At this time, the data is only modified in the memory, and the save method of the data context is called, which is saved to the persistent layer.
4. query data
After insertCoreData is called, you can call the custom query method dataFetchRequest to query the inserted data.
- (void)dataFetchRequest{ NSManagedObjectContext *context = [self managedObjectContext]; NSFetchRequest *fetchRequest = [[[NSFetchRequest alloc] init] autorelease]; NSEntityDescription *entity = [NSEntityDescription entityForName:@"ContactInfo" inManagedObjectContext:context]; [fetchRequest setEntity:entity]; NSError *error; NSArray *fetchedObjects = [context executeFetchRequest:fetchRequest error:&error]; for (NSManagedObject *info in fetchedObjects) { NSLog(@"name:%@", [info valueForKey:@"name"]); NSLog(@"age:%@", [info valueForKey:@"age"]); NSLog(@"birthday:%@", [info valueForKey:@"birthday"]); NSManagedObject *details = [info valueForKey:@"details"]; NSLog(@"address:%@", [details valueForKey:@"address"]); NSLog(@"telephone:%@", [details valueForKey:@"telephone"]); }}
FetchRequest is equivalent to the packaging class of SQL query statements. You must use the setEntity method to specify the object structure (table structure) of a specific query)
The NSEntityDescription entityForName method is used to return a pointer to the specific object structure.
Call the executeFetchRequest: error: Method to perform the query operation. If the operation succeeds, the corresponding data record array is returned.
You can use the NSManagedObject data record object to query the attributes of another data record object.
5. Data templates
Generates an NSManagedObject subclass for each object.
The preceding Key-Value method is used to set data and obtain data. A better way is to generate a subclass of a strong NSManagedObject class and access and obtain data through its member attributes.
(1) Select an entity object in the data editor view,
Select the file menu, click new, click file..., select the Core Data item, and select NSManagedObject subclass to generate a class with the same name as the object,
Inherited from NSManagedObject
Generate the corresponding ContactInfo. h file
#import <Foundation/Foundation.h>#import <CoreData/CoreData.h> @class ContactDetailInfo; @interface ContactInfo : NSManagedObject @property (nonatomic, retain) NSString * age;@property (nonatomic, retain) NSString * birthday;@property (nonatomic, retain) NSString * name;@property (nonatomic, retain) ContactDetailInfo *details; @end
Among them, @ dynamic tells the compiler not to handle it, so that the compilation passes. Its getter and setter methods will be dynamically created at runtime, and the Core Data framework will generate an access method for this class attribute.
#import "ContactInfo.h"#import "ContactDetailInfo.h"@implementation ContactInfo @dynamic age;@dynamic birthday;@dynamic name;@dynamic details; @end
#import <Foundation/Foundation.h>#import <CoreData/CoreData.h> @class ContactInfo; @interface ContactDetailInfo : NSManagedObject @property (nonatomic, retain) NSString * address;@property (nonatomic, retain) NSString * name;@property (nonatomic, retain) NSString * telephone;@property (nonatomic, retain) ContactInfo *info; @end
And ContactDetailInfo. m Files
#import "ContactDetailInfo.h"#import "ContactInfo.h" @implementation ContactDetailInfo @dynamic address;@dynamic name;@dynamic telephone;@dynamic info; @end
In this case, in the rightmost Sidebar of the data model editor view, the object class is changed to a specific class name.
The code using Key-Value can be changed:
#import "ContactInfo.h"#import "ContactDetailInfo.h"
-(Void) insertCoreData {custom * context = [self managedObjectContext]; ContactInfo * contactInfo = [NSEntityDescription metadata: @ "ContactInfo" inManagedObjectContext: context]; contactInfo. name = @ "name B"; contactInfo. birthday = @ "birthday B"; contactInfo. age = @ "age B"; ContactDetailInfo * contactDetailInfo = [NSEntityDescription insertNewObjectForEntityForNam E: @ "ContactDetailInfo" inManagedObjectContext: context]; contactDetailInfo. address = @ "address B"; contactDetailInfo. name = @ "name B"; contactDetailInfo. telephone = @ "telephone B"; contactDetailInfo.info = contactInfo; contactInfo. details = contactDetailInfo; NSError * error; if (! [Context save: & error]) {NSLog (@ "cannot be saved: % @", [error localizedDescription]) ;}}
- (void)dataFetchRequest{ NSManagedObjectContext *context = [self managedObjectContext]; NSFetchRequest *fetchRequest = [[[NSFetchRequest alloc] init] autorelease]; NSEntityDescription *entity = [NSEntityDescription entityForName:@"ContactInfo" inManagedObjectContext:context]; [fetchRequest setEntity:entity]; NSError *error; NSArray *fetchedObjects = [context executeFetchRequest:fetchRequest error:&error]; for (ContactInfo *info in fetchedObjects) { NSLog(@"name:%@", info.name); NSLog(@"age:%@", info.age); NSLog(@"birthday:%@", info.birthday); ContactDetailInfo *details = info.details; NSLog(@"address:%@", details.address); NSLog(@"telephone:%@", details.telephone); }}
Iii. Database Problems
1. Print the hidden SQL statement:
In Edit Scheme, select Run and enter the Arguments tag to add the parameter "-com. apple. CoreData. SQLDebug 1"
2. database structure when using SQLite for storage
Name of the stored SQLite database table: Capital "Z" and entity name in upper case. An object is equivalent to a table.
Specific field name: uppercase "Z" and entity attribute name in uppercase