iOS代码重构(二)CoreData多线程(支持线程安全)

CoreData对多线程的支持比较奇怪(按照一般的思路来说),CoreData的NSPersistentStoreCoordinator和NSManagedObjectContext对象都是不能跨线程使用的,NSManagedObject也不行,有人想加锁不就完了。

前提描述

     原项目中已有CoreData封装,但是线程不完全的,而且应用的地方较多,参考了网上的一些文章,如果按主流的搞个三层上下文saveMOC,mainMOC,newPrivateMOC,应用Block来实现异步。但项目改动较大。而且经测试,代码健壮性不是很好,多线程操作时,

有崩溃现象。原项目中的数据库文件,是按用户,分别创建的。

    基本方案:应用MagicRecord部分API,实现Core线程安全, 改动控制在CoreDataManager内

MagicRecord实现的是三层结构,

[NSManagedObjectContext MR_rootSavingContext] 根MOC

[NSManagedObjectContext MR_defaultContext] 对应MainMOC,主MOC,它的父是rootSavingContext

[NSManagedObjectContext MR_context] 对应privateMoc,私有MOC,它的父是defualtContext,每次调用都会新创建一个MOC



直接上代码吧

1 初始化操作

AppDelegate.m

NSString *userId = [[PublicObjectpublicObjectInstance] getUserId];

    if (userId) {//登录后再初始化本地数据库

        [[CoreDataManagershareInstance] setupCoreDataStack];

        [MagicalRecordsetLoggingLevel:MagicalRecordLoggingLevelAll];

    }


2 CoreDataManager部分函数

- (void) setupCoreDataStack

{

    if ([NSPersistentStoreCoordinatorMR_defaultStoreCoordinator] !=nil) return;

    

    NSPersistentStoreCoordinator *coordinator = [selfpersistentStoreCoordinator];

    [NSPersistentStoreCoordinatorMR_setDefaultStoreCoordinator:coordinator];

    

    [NSManagedObjectContextMR_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 = [[NSBundlemainBundle] URLForResource:@"ModelObject"withExtension:@"momd"];

        _managedObjectModel = [[NSManagedObjectModelalloc] 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 = [NSURLfileURLWithPath:[FileHelperinfodbFilePath]];//Lib目录/用户ID/info.db

        NSError *error =nil;

        _persistentStoreCoordinator = [[NSPersistentStoreCoordinatoralloc] initWithManagedObjectModel:[selfmanagedObjectModel]];

        NSDictionary *options =@{NSMigratePersistentStoresAutomaticallyOption : [NSNumbernumberWithBool:YES],

                                  NSInferMappingModelAutomaticallyOption : [NSNumbernumberWithBool:YES]};

        if (![_persistentStoreCoordinatoraddPersistentStoreWithType:NSSQLiteStoreTypeconfiguration:nilURL:storeURL options:optionserror:&error]) {

            NSLog(@"Unresolved error %@, %@", error, [erroruserInfo]);

            abort();

        }

    }

    return_persistentStoreCoordinator;

}

-(BOOL) save:(NSError **)error{

    [[NSManagedObjectContextMR_defaultContext] MR_saveToPersistentStoreAndWait];

    returnYES;

}

- (void)removeObjectsWithPredicate:(NSPredicate*)predicate inEntity:(NSString*)entityName {

    NSManagedObjectContext *context = [NSManagedObjectContextMR_context];

    NSFetchRequest *request = [[NSFetchRequestalloc] init];

    request.predicate = predicate;

    request.includesPropertyValues =NO;

    request.entity = [NSEntityDescriptionentityForName:entityNameinManagedObjectContext:context];

    

    [context performBlockAndWait:^{

        NSError *error;

        NSArray *objects = [contextexecuteFetchRequest:requesterror:&error];

        if (!error && objects.count) {

            for (NSManagedObject *objin objects) {

                [context deleteObject:obj];

            }

        }

    }];

    [context MR_saveToPersistentStoreAndWait];

}


- (NSMutableArray*)findObjectsIn:(NSString*)entityName withPredicate:(NSPredicate*)predicate andSortDescriptors:(NSArray*)sortDescriptors andObjectClass:(Class)objClass {

    

    

    NSManagedObjectContext *context = [NSManagedObjectContextMR_context];

    NSFetchRequest *request = [[NSFetchRequestalloc] init];

    request.predicate = predicate;

    request.sortDescriptors = sortDescriptors;

    request.entity = [NSEntityDescriptionentityForName:entityNameinManagedObjectContext:context];

    

    __blockNSMutableArray *results =nil;

    [context performBlockAndWait:^{

        

        NSError *error =nil;

        NSArray *objects = [contextexecuteFetchRequest:requesterror:&error];

        if (objects ==nil)

        {

            NSLog(@"%@",error);

            return ;

        }

        results = [NSMutableArrayarrayWithCapacity:objects.count];

        if (!error && objects.count) {

            for (id entityin objects) {

                id obj = [[objClassalloc] initWithEntity:entity];

                [results addObject:obj];

            }

        }

        

        

        

    }];

    return results;


}

//插入

- (void)insertProgressAndAttachments:(NSArray *)progressArray

{

    NSManagedObjectContext *context = [NSManagedObjectContextMR_context];

    for (Progress *progressin progressArray) {

        Progress* entity = (Progress*)[NSEntityDescriptioninsertNewObjectForEntityForName: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 *attachin progress.attachments) {

            [selfinsertProgressAttachment:attach];

        }

        

        for (ProgressWorkType *workTypein progress.workTypes) {

            [selfinsertProgressWorkType:workType];

        }

        

        for (ProgressDelayReason *delayReasonin progress.delayReasons) {

            [selfinsertProgressDelayReason:delayReason];

        }

    }

    [context MR_saveToPersistentStoreAndWait];

}

//查找

- (Progress*)findProgressById:(NSString *)progressId {

    return [selffindFirstObjectIn:TBProgress

                     withPredicate:[NSPredicatepredicateWithFormat:@"progressId = %@", progressId]

                andSortDescriptors:nil

                    andObjectClass:[Progressclass]];

}

//删除

// 删除一个项目的所有进度附件

- (void)removeAllProgressAttachmentByProject:(NSString*)projectId {

    [selfremoveObjectsWithPredicate:[NSPredicatepredicateWithFormat:@"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.cocoanetics.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



     
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值