线程核心数据混淆实现

时间:2014-12-10 04:58:30

标签: ios multithreading core-data

最近,我一直在挖掘很多关于Threaded CoreData的内容,我读了这些教程:

就个人而言,我对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服务无法运行。并且它们在主线程中启动主线程上下文和BackgroundThread上下文。之后,他们只传递backgroundContext以在Background中使用。

- (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);
                }
            }
        }];
    }];
}
个人而言,我认为问题10核心数据网络应用程序的实现方式是完全错误的,并没有遵循苹果规则,我们必须创建每个后台线程NSManageObjectContext。这样对吗?请给我你的意见。哪种方式实现正确?。

1 个答案:

答案 0 :(得分:0)

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