An atomic persistent store needs to be completely deserialized and loaded into memory before you can make any read or write operations. In contrast, a non- atomic persistent store can load chunks of itself onto memory as needed.
## type
NSSQLiteStoreType (nonatomic)
NSXMLStoreType (atomic)
NSBinaryStoreType (atomic)
NSInMemoryStoreType (atomic)
# 4.2 NSPersistentStoreCoordinator
the bridge between the managed object model and the persistent store
通过managed object model初始化
通过addPersistentStoreWithType:configuration:URL:options:error: 添加persistent store
-(void)saveContext{NSError*error;if([self.managedContexthasChanges]&&![self.managedContextsave:&error]){NSLog(@"NSManagedObjectContext Save Error: %@",[errorlocalizedDescription]);}}
@property(readonly,strong)NSPersistentContainer*persistentContainer;-(NSPersistentContainer*)persistentContainer{// The persistent container for the application. This implementation creates and returns a container, having loaded the store for the application to it.@synchronized(self){if(_persistentContainer==nil){_persistentContainer=[[NSPersistentContaineralloc]initWithName:@"testCoreData"];[_persistentContainerloadPersistentStoresWithCompletionHandler:^(NSPersistentStoreDescription*storeDescription,NSError*error){if(error!=nil){// Replace this implementation with code to handle the error appropriately.// abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development./* Typical reasons for an error here include: * The parent directory does not exist, cannot be created, or disallows writing. * The persistent store is not accessible, due to permissions or data protection when the device is locked. * The device is out of space. * The store could not be migrated to the current model version. Check the error message to determine what the actual problem was. */NSLog(@"Unresolved error %@, %@",error,error.userInfo);abort();}}];}}return_persistentContainer;}-(void)saveContext{NSManagedObjectContext*context=self.persistentContainer.viewContext;NSError*error=nil;if([contexthasChanges]&&![contextsave:&error]){// Replace this implementation with code to handle the error appropriately.// abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.NSLog(@"Unresolved error %@, %@",error,error.userInfo);abort();}}
NSManagedObject is a generic class that implements all the basic behavior required of a Core Data model object. It is not possible to use instances of direct subclasses of NSObject (or any other class not inheriting from NSManagedObject) with a managed object context. You may create custom subclasses of NSManagedObject, although this is not always required. If no custom logic is needed, a complete Object graph can be formed with NSManagedObject instances.
在Xcode Data Model Editor 中选中你要创建NSManagedObject子类的实例,在右侧Data Model Inspector中选择Codegen
Manual/None
Manual/None is the default, and previous behavior; in this case you should implement your own subclass or use NSManagedObject.
这个是iOS10以前的默认行为,需要我们手动通过Xcode Editor-> Create NSManagedObject SubClass… 生成ClassName+CoreDataClass 文件以及 ClassName+CoreDataGeneratedProperties 其中前者,是类的定义,以及类行为定义,后者通过category 定义了类的属性(注:Objective-C中Category定义属性不支持生成成员变量,但可以生成get set 方法,CoreData属性通过@dynamic修饰,表示,运行时生成 get set 方法)
当每次修改,data model的时候,重新通过以上方法,生成NSManagedObject对象,系统只会覆盖ClassName+CoreDataGeneratedProperties文件,而不会修改ClassName+CoreDataClass 文件。
- Category/Extension.
- Category/Extension generates a class extension in a file named like ClassName+CoreDataGeneratedProperties. You need to declare/implement the main class (if in Obj-C, via a header the extension can import named ClassName.h).
一般情况下,因为我们不需要修改属性Category的定义,而只需要修改类行为的定义,所以这个选项,就直接不对开发者暴露Category 文件,当你修改了DataModel的时候,就可以自动同步最新的代码
- Class Definition
- Class Definition generates subclass files named like ClassName+CoreDataClass as well as the files generated for Category/Extension.
Prior to iOS 5, fetching by ID was popular because NSManagedObjectID is thread-safe and using it helped developers implement the thread confinement concurrency model. Now that thread confinement has been deprecated in favor of more modern concurrency models, there’s little reason to fetch by object ID anymore.
# 2. NSPredicate
The NSPredicate class is used to define logical conditions used to constrain a search either for a fetch or for in-memory filtering.
-(BOOL)application:(UIApplication*)applicationdidFinishLaunchingWithOptions:(NSDictionary*)launchOptions{// Override point for customization after application launch.[selfimportSeedJsonSeedIfNeeded];returnYES;}-(void)importSeedJsonSeedIfNeeded{NSManagedObjectContext*context=[[MTCoreDataStacksharedInstance]managedContext];NSFetchRequest*fetchRequest=[MasterfetchRequest];fetchRequest.resultType=NSCountResultType;NSError*error;NSArray*results=[contextexecuteFetchRequest:fetchRequesterror:&error];if(!error){if([resultscount]>0){NSIntegermasterCount=[[resultsobjectAtIndex:0]integerValue];if(masterCount<=0){[selfimportJsonSeed];}}else{[selfimportJsonSeed];}}else{[selfimportJsonSeed];}}-(void)importJsonSeed{NSURL*jsonURL=[[NSBundlemainBundle]URLForResource:@"seed"withExtension:@"json"];NSError*error;NSData*jsonData=[NSDatadataWithContentsOfURL:jsonURLoptions:0error:&error];if(!error){NSDictionary*jsonDict=[NSJSONSerializationJSONObjectWithData:jsonDataoptions:0error:&error];if(!error){NSManagedObjectContext*context=[[MTCoreDataStacksharedInstance]managedContext];NSEntityDescription*masterEntity=[NSEntityDescriptionentityForName:@"Master"inManagedObjectContext:context];NSEntityDescription*dogeEntity=[NSEntityDescriptionentityForName:@"Doge"inManagedObjectContext:context];NSDictionary*masterDict=jsonDict[@"master"];if(![masterDictisKindOfClass:[NSDictionaryclass]]){return;}Master*master=[[Masteralloc]initWithEntity:masterEntityinsertIntoManagedObjectContext:context];master.name=masterDict[@"name"];master.age=[masterDict[@"age"]integerValue];NSArray*doges=jsonDict[@"doges"];for(NSDictionary*dogeDictindoges){if(![dogeDictisKindOfClass:[NSDictionaryclass]]){continue;}Doge*doge=[[Dogealloc]initWithEntity:dogeEntityinsertIntoManagedObjectContext:context];doge.name=dogeDict[@"name"];doge.age=[dogeDict[@"age"]integerValue];doge.master=master;//因为在DataModel 里设置了 inverse, 所以master 和 doge可以相互关联上}//一定要调用 save 方法,才能真正的将文件存入数据库[[MTCoreDataStacksharedInstance]saveContext];}}}