线程化核心数据混淆实现

Posted

技术标签:

【中文标题】线程化核心数据混淆实现【英文标题】:Threaded Core Data Confuse Implement 【发布时间】:2014-12-10 04:58:29 【问题描述】:

最近,我一直在深入研究 Threaded CoreData,我阅读了这些教程:

ZACoreData issue-10-core-data-network-application

就个人而言,我对 ZACoreData 方式感到满意。因为它坚持苹果规则。这会为每个线程创建一个上下文。

    + (NSManagedObjectContext *) contextForCurrentThread

    if (!_managedObjectContextsDictionary) 
        _managedObjectContextsDictionary = [[NSMutableDictionary alloc] init];
    

    // Force the return of the main thread context.
    if ([NSThread isMainThread]) 
        return [NSManagedObjectContext contextForMainThread];
    

    NSThread *currentThread = [NSThread currentThread];
    if (![[currentThread name] length]) 
        [currentThread setName: [NSManagedObjectContext generateGUID]];

        NSManagedObjectContextConcurrencyType contextType = ([currentThread isMainThread]) ? NSMainQueueConcurrencyType : NSPrivateQueueConcurrencyType;

        NSManagedObjectContext *context = [[NSManagedObjectContext alloc] initWithConcurrencyType: contextType];

        if ([currentThread isMainThread]) 
            context.persistentStoreCoordinator = [NSPersistentStoreCoordinator sharedPersisntentStoreCoordinator];
        

        if (![currentThread isMainThread]) 
            context.parentContext = [NSManagedObjectContext contextForMainThread];
        
        [_managedObjectContextsDictionary setObject:context forKey: [currentThread name]];

        return context;
     else 
        return [_managedObjectContextsDictionary objectForKey: [currentThread name]];
    

但是我的老板不想这样实现,他更喜欢使用 issue-10-core-data-network-application,这个演示甚至无法运行,因为他们的 web 服务无法运行。他们在主线程中同时初始化主线程上下文和背景线程上下文。之后,他们只需传递 backgroundContext 以在后台使用。

- (void)setupManagedObjectContexts

    self.managedObjectContext = [self setupManagedObjectContextWithConcurrencyType:NSMainQueueConcurrencyType];
    self.managedObjectContext.undoManager = [[NSUndoManager alloc] init];

    self.backgroundManagedObjectContext = [self setupManagedObjectContextWithConcurrencyType:NSPrivateQueueConcurrencyType];
    self.backgroundManagedObjectContext.undoManager = nil;


    [[NSNotificationCenter defaultCenter]
            addObserverForName:NSManagedObjectContextDidSaveNotification
                        object:nil
                         queue:nil
                    usingBlock:^(NSNotification* note) 
        NSManagedObjectContext *moc = self.managedObjectContext;
        if (note.object != moc) 
            [moc performBlock:^()
                [moc mergeChangesFromContextDidSaveNotification:note];
            ];
        
     ];

他们是这样使用的:

- (void)import

    self.batchCount = 0;
    [self.webservice fetchAllPods:^(NSArray *pods)
    
        [self.context performBlock:^
        
            for(NSDictionary *podSpec in pods) 
                NSString *identifier = [podSpec[@"name"] stringByAppendingString:podSpec[@"version"]];
                Pod *pod = [Pod findOrCreatePodWithIdentifier:identifier inContext:self.context];
                [pod loadFromDictionary:podSpec];
            
            self.batchCount++;
            if (self.batchCount % 10 == 0) 
                NSError *error = nil;
                [self.context save:&error];
                if (error) 
                    NSLog(@"Error: %@", error.localizedDescription);
                
            
        ];
    ];

就我个人而言,我认为 issue-10-core-data-network-application 的实现方式是完全错误的,不符合苹果规则,即我们必须为每个后台线程创建一个 NSManageObjectContext。这样对吗?请给我你的意见。哪种方式实施正确?

【问题讨论】:

【参考方案1】:

使用私有队列创建的托管对象上下文可以在主线程上创建,然后在其他地方使用。重要的部分是上下文的内容(或从上下文中获取的任何对象)只能在performBlock 中使用,因为该代码在与上下文的私有队列关联的线程上运行(这是关于上下文不跨线程共享的原始命令的关键点)。

【讨论】:

谢谢各位。现在有了教程二,我就更清楚了。 没问题,请投票并勾选有助于解决您问题的问题;-)

以上是关于线程化核心数据混淆实现的主要内容,如果未能解决你的问题,请参考以下文章

线程化核心数据和 UINavigationController

java多线程编程核心技术怎么样

删除请求并将 RESTkit 与核心数据和线程同步

二期 0005 线程池原理剖析&锁的深度化

核心数据多线程——我做错了啥

Java多线程核心技术单例模式与多线程