CoreData的構(gòu)成:
(1)NSManagedObjectContext 被管理者對象上下文宛畦,相當(dāng)于一個未存儲的臨時數(shù)據(jù)庫趋观,我們存儲或者查詢都是通過這個對象來的扩然。
(2)NSManagedObjectModel 被管理對象模型梳星,可以簡單的理解為可視化建模文件菜秦,可視化建模中是Entity自動生成model 方便讓文件存儲助理來進行管理怪得。
(3)NSPersistentStoreCoordinator 文件存儲助理咱枉,相當(dāng)于數(shù)據(jù)庫的鏈接器,它是CpreData的核心負(fù)責(zé)鏈接所有的模塊徒恋,包括真實的存儲文件蚕断。
(4)NSManagedObject 被管理的數(shù)據(jù)記錄, 相當(dāng)于數(shù)據(jù)庫中的表格記錄入挣。
(5)NSFetchRequest 獲取數(shù)據(jù)的請求亿乳,相當(dāng)于SQL語句。
(6)NSEntityDescription 實體結(jié)構(gòu)径筏,相當(dāng)于表結(jié)構(gòu)葛假。
(7)后綴為.xcdatamodeld的包 里面是.xcodemodel文件 用數(shù)據(jù)模型編輯器編譯障陶。編譯后為.momd或.mom文件。
一些細節(jié):
1桐款、NSManagedObjectContext創(chuàng)建時apple推薦使用參數(shù)NSPrivateQueueConcurrencyType或NSMainQueueConcurrencyType咸这,二者區(qū)別如下:
使用NSMainQueueConcurrencyType初始化時,block將會在主線程中執(zhí)行
[_context performBlock:^(){
[_context save:nil];
}];
使用NSPrivateQueueConcurrencyType初始化時魔眨,block將會在新子線程中執(zhí)行媳维,此中情況下涉及到更新UI的操作需要在主線程中調(diào)用,因此可以改進如下:
[_context performBlock:^(){
[_context save:nil];
dispatch_async(dispatch_get_main_queue(), ^{
[_tableView reloadData];
[self scrollToBottom];
});
}];
2遏暴、MOC不是線程安全的侄刽,多個線程不能使用同一個,因此多線程使用MOC可以使用parent-child方法解決朋凉,每個子線程有一個MOC州丹,主線程有一個MOC,主線程MOC是子線程MOC的parentContext杂彭。
例子如下:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(){
NSManagedObjectContext *childcontext = [[NSManagedObjectContext alloc]initWithConcurrencyType:NSPrivateQueueConcurrencyType];
childcontext.parentContext = _context;
[childcontext performBlock:^(){
Person *person = [NSEntityDescription insertNewObjectForEntityForName:@"Person" inManagedObjectContext:childcontext];
person.name = [NSString stringWithFormat:@"json%i",count++];
person.age = [NSNumber numberWithUnsignedInt:20];
person.timestamp = [NSDate date];
NSManagedObjectID *personid = person.objectID;
[childcontext save:nil];
[_context performBlock:^(){
[_context save:nil];
[_contextWrite performBlockAndWait:^(){
if ([_contextWrite hasChanges])
{
[_contextWrite save:nil];
}
}];
dispatch_async(dispatch_get_main_queue(), ^(){
[self.dataList addObject:[_contextWrite objectWithID:personid]];
[_tableView reloadData];
[self scrollToBottom];
});
}];
}];
});
以上parentcontext(main)<---childcontext(private)結(jié)構(gòu)就可以解決大多數(shù)問題了墓毒,因為數(shù)據(jù)庫的復(fù)雜操作往往來自于查詢,尤其那些正則匹配亲怠、模糊查找所计,而將這些費時的操作放入childcontext中有多線程異步處理,可以不阻塞主線程团秽。
上面的結(jié)構(gòu)相當(dāng)于將寫入數(shù)據(jù)庫的操作放在主線程中執(zhí)行主胧,因此對于大量寫入數(shù)據(jù)庫的情況是不適用的。而此時則可以使用三層結(jié)構(gòu)解決:grandcontext(private)<---parentcontext(main)<---childcontext(private)习勤,其中childcontext負(fù)責(zé)數(shù)據(jù)處理查詢踪栋,parentcontext用于同步操作、解決線程安全問題图毕,grandcontext則用于寫入操作夷都。
3、多線程之間是不允許傳遞NSManagedObject的吴旋,但是可以通過傳遞NSManagedObjectID來解決损肛。