CoreData對多線程的支持比擬奇異(依照普通的思緒來說),CoreData的NSPersistentStoreCoordinator和NSManagedObjectContext對象都是不能跨線程運用的,NSManagedObject也不行,有人想加鎖不就完了。
前提描繪
原項目中已有CoreData封裝,但是線程不完全的,而且使用的中央較多,參考了網上的一些文章,假如按主流的搞個三層上下文saveMOC,mainMOC,newPrivateMOC,使用Block來完成異步。但項目改動較大。而且經測試,代碼強健性不是很好,多線程操作時,
有解體景象。原項目中的數據庫文件,是按用戶,辨別創立的。
根本方案:使用MagicRecord局部API,完成Core線程平安。
直接上代碼吧
1 初始化操作
AppDelegate.m
NSString *userId = [[PublicObject publicObjectInstance] getUserId];
if (userId) {//登錄後再初始化本地數據庫
[[CoreDataManager shareInstance] setupCoreDataStack];
[MagicalRecord setLoggingLevel:MagicalRecordLoggingLevelAll];
}
2 CoreDataManager局部函數
- (void) setupCoreDataStack
{
if ([NSPersistentStoreCoordinator MR_defaultStoreCoordinator] != nil) return;
NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
[NSPersistentStoreCoordinator MR_setDefaultStoreCoordinator:coordinator];
[NSManagedObjectContext MR_initializeDefaultContextWithCoordinator:coordinator];
}
// Returns the managed object model for the application.
// If the model doesn't already exist, it is created from the application's model.
- (NSManagedObjectModel *)managedObjectModel {
if (!_managedObjectModel) {
NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"ModelObject" withExtension:@"momd"];
_managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
}
return _managedObjectModel;
}
// Returns the persistent store coordinator for the application.
// If the coordinator doesn't already exist, it is created and the application's store added to it.
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator {
if (!_persistentStoreCoordinator) {
NSURL* storeURL = [NSURL fileURLWithPath:[FileHelper infodbFilePath]];//Lib目錄/用戶ID/info.db
NSError *error = nil;
_persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];
NSDictionary *options = @{NSMigratePersistentStoresAutomaticallyOption : [NSNumber numberWithBool:YES],
NSInferMappingModelAutomaticallyOption : [NSNumber numberWithBool:YES]};
if (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:options error:&error]) {
NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
abort();
}
}
return _persistentStoreCoordinator;
}
-(BOOL) save:(NSError **)error{
[[NSManagedObjectContext MR_defaultContext] MR_saveToPersistentStoreAndWait];
return YES;
}
- (void)removeObjectsWithPredicate:(NSPredicate*)predicate inEntity:(NSString*)entityName {
NSManagedObjectContext *context = [NSManagedObjectContext MR_context];
NSFetchRequest *request = [[NSFetchRequest alloc] init];
request.predicate = predicate;
request.includesPropertyValues = NO;
request.entity = [NSEntityDescription entityForName:entityName inManagedObjectContext:context];
[context performBlockAndWait:^{
NSError *error;
NSArray *objects = [context executeFetchRequest:request error:&error];
if (!error && objects.count) {
for (NSManagedObject *obj in objects) {
[context deleteObject:obj];
}
}
}];
[context MR_saveToPersistentStoreAndWait];
}
- (NSMutableArray*)findObjectsIn:(NSString*)entityName withPredicate:(NSPredicate*)predicate andSortDescriptors:(NSArray*)sortDescriptors andObjectClass:(Class)objClass {
NSManagedObjectContext *context = [NSManagedObjectContext MR_context];
NSFetchRequest *request = [[NSFetchRequest alloc] init];
request.predicate = predicate;
request.sortDescriptors = sortDescriptors;
request.entity = [NSEntityDescription entityForName:entityName inManagedObjectContext:context];
__block NSMutableArray *results = nil;
[context performBlockAndWait:^{
NSError *error = nil;
NSArray *objects = [context executeFetchRequest:request error:&error];
if (objects == nil)
{
NSLog(@"%@",error);
return ;
}
results = [NSMutableArray arrayWithCapacity:objects.count];
if (!error && objects.count) {
for (id entity in objects) {
id obj = [[objClass alloc] initWithEntity:entity];
[results addObject:obj];
}
}
}];
return results;
}
//拔出
- (void)insertProgressAndAttachments:(NSArray *)progressArray
{
NSManagedObjectContext *context = [NSManagedObjectContext MR_context];
for (Progress *progress in progressArray) {
Progress* entity = (Progress*)[NSEntityDescription insertNewObjectForEntityForName:TBProgress
inManagedObjectContext:context];
entity.projectId = progress.projectId;
entity.buildingId = progress.buildingId;
entity.progressId = progress.progressId;
entity.createdDate = progress.createdDate;
entity.createdBy = progress.createdBy;
entity.lastModifiedDate = progress.lastModifiedDate;
entity.lastModifiedBy = progress.lastModifiedBy;
entity.occurredDate = progress.occurredDate;
entity.progressDesc = progress.progressDesc;
entity.version = progress.version;
entity.progressStatus = progress.progressStatus;
entity.conflict = progress.conflict;
entity.weather = progress.weather;
entity.temperature = progress.temperature;
entity.WindPower = progress.WindPower;
for (ProgressAttachment *attach in progress.attachments) {
[self insertProgressAttachment:attach];
}
for (ProgressWorkType *workType in progress.workTypes) {
[self insertProgressWorkType:workType];
}
for (ProgressDelayReason *delayReason in progress.delayReasons) {
[self insertProgressDelayReason:delayReason];
}
}
[context MR_saveToPersistentStoreAndWait];
}
//查找
- (Progress*)findProgressById:(NSString *)progressId {
return [self findFirstObjectIn:TBProgress
withPredicate:[NSPredicate predicateWithFormat:@"progressId = %@", progressId]
andSortDescriptors:nil
andObjectClass:[Progress class]];
}
//刪除
// 刪除一個項目的一切進度附件
- (void)removeAllProgressAttachmentByProject:(NSString*)projectId {
[self removeObjectsWithPredicate:[NSPredicate predicateWithFormat:@"projectId = %@", projectId]
inEntity:TBProgressAttachment];
}
參考文章:
源碼
https://github.com/search?utf8=✓&q=IOS+coredata+thread
原理-知識
看法CoreData—多線程
http://www.tuicool.com/articles/2iimue
IOS開發中一些罕見的並行處置
http://www.cocoachina.com/industry/20131212/7525.html
對應Demo
https://github.com/Acorld/IOS_CoreData_MutThread_Demo
在多線程環境中運用CoreData
http://www.iliunian.com/2896.html
英文版
https://www.coco.netics.com/2012/07/multi-context-coredata/
不再替Core Data多線程編程而頭疼
http://www.myexception.cn/program/1937577.html
Magical Record 片面解析
http://www.jianshu.com/p/590c6db9cdd6
MagicalRecord 初始化,數據遷移與提早預制數據庫邏輯
http://www.jianshu.com/p/cd1a06c7ce09
【iOS代碼重構(二)CoreData多線程(支持線程平安)】的相關資料介紹到這裡,希望對您有所幫助! 提示:不會對讀者因本文所帶來的任何損失負責。如果您支持就請把本站添加至收藏夾哦!