NSManagedObject
上篇文章Core Data學(xué)習(xí)筆記一:創(chuàng)建CoreDataStack創(chuàng)建了Data Model 文件,并且創(chuàng)建了一些實(shí)例Entity 如果說(shuō),可視化Data Model文件在程序中,對(duì)應(yīng)了NSManagedModel對(duì)象,這些Entity在程序中,所對(duì)應(yīng)的對(duì)象就是NSManagedObject (當(dāng)然其實(shí)并不完全對(duì)等,可以先這么理解)
Document
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.
這里大概有三個(gè)要點(diǎn)
- NSManagedObject 代表了Data Model中的對(duì)象
- NSManagedObject 需要和 NSManagedObjectContext 結(jié)合使用才有意義
- NSManagedObject 滿足所有你自定義的model 對(duì)象需求,通過(guò)KVC 去訪問(wèn)相應(yīng)的屬性
生成NSManagedObject子類
雖然通過(guò)KVC就可以訪問(wèn)NSManagedObject所有的屬性,但這樣使用起來(lái)不是很方便。
在Xcode Data Model Editor 中選中你要?jiǎng)?chuàng)建NSManagedObject子類的實(shí)例,在右側(cè)Data Model Inspector中選擇Codegen

- Manual/None
- Category/Extension.
- Class Definition
Manual/None is the default, and previous behavior; in this case you should implement your own subclass or use NSManagedObject.
這個(gè)是iOS10以前的默認(rèn)行為,需要我們手動(dòng)通過(guò)Xcode Editor-> Create NSManagedObject SubClass... 生成ClassName+CoreDataClass 文件以及 ClassName+CoreDataGeneratedProperties 其中前者,是類的定義,以及類行為定義,后者通過(guò)category 定義了類的屬性(注:Objective-C中Category定義屬性不支持生成成員變量,但可以生成get set 方法,CoreData屬性通過(guò)@dynamic修飾,表示,運(yùn)行時(shí)生成 get set 方法)
當(dāng)每次修改,data model的時(shí)候,重新通過(guò)以上方法,生成NSManagedObject對(duì)象,系統(tǒng)只會(huì)覆蓋ClassName+CoreDataGeneratedProperties文件,而不會(huì)修改ClassName+CoreDataClass 文件。
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).
一般情況下,因?yàn)槲覀儾恍枰薷膶傩訡ategory的定義,而只需要修改類行為的定義,所以這個(gè)選項(xiàng),就直接不對(duì)開發(fā)者暴露Category 文件,當(dāng)你修改了DataModel的時(shí)候,就可以自動(dòng)同步最新的代碼
Class Definition generates subclass files named like ClassName+CoreDataClass as well as the files generated for Category/Extension.
當(dāng)我們也不需要為NSManagedObject定義行為的時(shí)候,我們就可以選中這個(gè)選項(xiàng),然后直接在項(xiàng)目里引用頭文件就可以直接使用。
數(shù)據(jù)庫(kù) 增刪改查
增
增加一個(gè)數(shù)據(jù)庫(kù)對(duì)象,首先,需要?jiǎng)?chuàng)建一個(gè)NSEntityDescription,前面說(shuō) Data Model Editor 里的實(shí)例并不完全和NSManagedObject對(duì)等,就是因?yàn)閯?chuàng)建NSManagedObject對(duì)象,還需要entity相關(guān)的描述對(duì)象,這個(gè)對(duì)象才與實(shí)例對(duì)等。
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Doge" inManagedObjectContext:_context];
Doge *doge = [[Doge alloc] initWithEntity:entity insertIntoManagedObjectContext:_context];
doge.name = @"xxx";
...
...
//注意,這里并沒有實(shí)際把對(duì)象存入數(shù)據(jù)庫(kù),實(shí)際存入需要調(diào)用NSManagedObjectContext 的save:方法
[_context save:nil];
改
直接訪問(wèn)NSManagedObject屬性的set方法,就可以修改屬性,同時(shí),也只有當(dāng)調(diào)用了NSManagedObjectContext 的-save:方法后才能存入實(shí)際的存儲(chǔ)文件中
刪
刪除調(diào)用NSManagedObjectContext的-deleteObject:方法,然后調(diào)用-save:方法
Doge *doge = ...
[_context deleteObject:doge];
[_context save:nil]
查
查 會(huì)單獨(dú)寫一篇學(xué)習(xí)筆記:)
Demo
添加數(shù)據(jù)
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
[self importSeedJsonSeedIfNeeded];
return YES;
}
- (void)importSeedJsonSeedIfNeeded {
NSManagedObjectContext *context = [[MTCoreDataStack sharedInstance] managedContext];
NSFetchRequest * fetchRequest = [Master fetchRequest];
fetchRequest.resultType = NSCountResultType;
NSError *error;
NSArray *results = [context executeFetchRequest:fetchRequest error:&error];
if (!error) {
if ([results count] > 0) {
NSInteger masterCount = [[results objectAtIndex:0] integerValue];
if (masterCount <= 0) {
[self importJsonSeed];
}
} else {
[self importJsonSeed];
}
}else {
[self importJsonSeed];
}
}
- (void)importJsonSeed {
NSURL *jsonURL = [[NSBundle mainBundle] URLForResource:@"seed" withExtension:@"json"];
NSError *error;
NSData *jsonData = [NSData dataWithContentsOfURL:jsonURL options:0 error:&error];
if (!error) {
NSDictionary *jsonDict = [NSJSONSerialization JSONObjectWithData:jsonData options:0 error:&error];
if (!error) {
NSManagedObjectContext *context = [[MTCoreDataStack sharedInstance] managedContext];
NSEntityDescription *masterEntity = [NSEntityDescription entityForName:@"Master" inManagedObjectContext:context];
NSEntityDescription *dogeEntity = [NSEntityDescription entityForName:@"Doge" inManagedObjectContext:context];
NSDictionary *masterDict = jsonDict[@"master"];
if (![masterDict isKindOfClass:[NSDictionary class]]) {
return;
}
Master *master = [[Master alloc] initWithEntity:masterEntity insertIntoManagedObjectContext:context];
master.name = masterDict[@"name"];
master.age = [masterDict[@"age"] integerValue];
NSArray *doges = jsonDict[@"doges"];
for (NSDictionary *dogeDict in doges) {
if (![dogeDict isKindOfClass:[NSDictionary class]]) {
continue;
}
Doge *doge = [[Doge alloc] initWithEntity:dogeEntity insertIntoManagedObjectContext:context];
doge.name = dogeDict[@"name"];
doge.age = [dogeDict[@"age"] integerValue];
doge.master = master; //因?yàn)樵贒ataModel 里設(shè)置了 inverse, 所以master 和 doge可以相互關(guān)聯(lián)上
}
//一定要調(diào)用 save 方法,才能真正的將文件存入數(shù)據(jù)庫(kù)
[[MTCoreDataStack sharedInstance] saveContext];
}
}
}
源碼下載
https://github.com/mengtian-li/CoreDataStackDemo/releases/tag/v0.2