NSManagedObject
上篇文章Core Data學習筆記一:創(chuàng)建CoreDataStack創(chuàng)建了Data Model 文件,并且創(chuàng)建了一些實例Entity
如果說,可視化Data Model文件在程序中,對應了NSManagedModel
對象,這些Entity
在程序中,所對應的對象就是NSManagedObject
(當然其實并不完全對等,可以先這么理解)
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.
這里大概有三個要點
- NSManagedObject 代表了Data Model中的對象
- NSManagedObject 需要和 NSManagedObjectContext 結(jié)合使用才有意義
- NSManagedObject 滿足所有你自定義的model 對象需求,通過KVC 去訪問相應的屬性
生成NSManagedObject子類
雖然通過KVC就可以訪問NSManagedObject所有的屬性,但這樣使用起來不是很方便。
在Xcode Data Model Editor 中選中你要創(chuàng)建NSManagedObject子類的實例,在右側(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.
這個是iOS10以前的默認行為,需要我們手動通過Xcode Editor-> Create NSManagedObject SubClass...
生成ClassName+CoreDataClass
文件以及 ClassName+CoreDataGeneratedProperties
其中前者,是類的定義,以及類行為定義,后者通過category 定義了類的屬性(注:Objective-C中Category定義屬性不支持生成成員變量,但可以生成get set 方法,CoreData屬性通過@dynamic修飾,表示,運行時生成 get set 方法)
當每次修改,data model的時候,重新通過以上方法,生成NSManagedObject對象,系統(tǒng)只會覆蓋ClassName+CoreDataGeneratedProperties
文件,而不會修改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).
一般情況下,因為我們不需要修改屬性Category的定義,而只需要修改類行為的定義,所以這個選項,就直接不對開發(fā)者暴露Category 文件,當你修改了DataModel的時候,就可以自動同步最新的代碼
Class Definition generates subclass files named like ClassName+CoreDataClass as well as the files generated for Category/Extension.
當我們也不需要為NSManagedObject
定義行為的時候,我們就可以選中這個選項,然后直接在項目里引用頭文件就可以直接使用。
數(shù)據(jù)庫 增刪改查
增
增加一個數(shù)據(jù)庫對象,首先,需要創(chuàng)建一個NSEntityDescription
,前面說 Data Model Editor 里的實例并不完全和NSManagedObject
對等,就是因為創(chuàng)建NSManagedObject
對象,還需要entity相關(guān)的描述對象,這個對象才與實例對等。
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Doge" inManagedObjectContext:_context];
Doge *doge = [[Doge alloc] initWithEntity:entity insertIntoManagedObjectContext:_context];
doge.name = @"xxx";
...
...
//注意,這里并沒有實際把對象存入數(shù)據(jù)庫,實際存入需要調(diào)用NSManagedObjectContext 的save:方法
[_context save:nil];
改
直接訪問NSManagedObject
屬性的set方法,就可以修改屬性,同時,也只有當調(diào)用了NSManagedObjectContext 的-save:
方法后才能存入實際的存儲文件中
刪
刪除調(diào)用NSManagedObjectContext
的-deleteObject:
方法,然后調(diào)用-save:
方法
Doge *doge = ...
[_context deleteObject:doge];
[_context save:nil]
查
查 會單獨寫一篇學習筆記:)
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; //因為在DataModel 里設(shè)置了 inverse, 所以master 和 doge可以相互關(guān)聯(lián)上
}
//一定要調(diào)用 save 方法,才能真正的將文件存入數(shù)據(jù)庫
[[MTCoreDataStack sharedInstance] saveContext];
}
}
}
源碼下載
https://github.com/mengtian-li/CoreDataStackDemo/releases/tag/v0.2