后台加载核心数据

时间:2014-04-02 22:48:55

标签: ios objective-c core-data

所以我已经阅读了一段时间的堆栈,我意识到我需要制作一个后台核心数据NSManagedObjectContext,因为我正在加载大量的记录而且我不想锁定UI。

我做的是以下内容:

backgroundContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];

NSPersistentStoreCoordinator *store = [[self managedObjectContext] persistentStoreCoordinator];

[backgroundContext setPersistentStoreCoordinator:store];

在我的函数调用中我直接执行:

 self.flightsFRC = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest
                                    managedObjectContext:backgroundContext
                                    sectionNameKeyPath:nil
                                    cacheName:@"FlightRecords"];

我的代码目前正在运行,但我感觉它是“坏”的其他地方,我直接访问FRC而不处理任何同步或任何类似于此处迭代通过Fetched Results Controller的任何内容。

FlightRecording *rec = [[[self flightsFRC] fetchedObjects] objectAtIndex:i];

我错过了什么吗?我应该以某种方式通过NSManagedObjectID加载记录这似乎“太容易了”

1 个答案:

答案 0 :(得分:1)

您目前的FRC指向背景上下文。不要这样做。只指向主线程上的上下文。

为了让您的FRC收到有关更改的通知,您实际上需要将后台上下文合并到主线程上下文中。当后台上下文保存时,您的CoreData堆栈对象需要注册通知:

[[NSNotificationCenter defaultCenter] addObserver:self
                                         selector:@selector(contextDidSave:)
                                             name:NSManagedObjectContextDidSaveNotification
                                           object:nil];

由于通知可以从其他线程发布,因此我们需要在触发时进行检查以确保我们在主线程上。如果我们已经在那里,那么我们可以在mergeChangesFromContextDidSaveNotification上调用NSManagedObjectContext API。

- (void)contextDidSave:(NSNotification *)notification {
    if (![NSThread isMainThread]) {
        dispatch_async(dispatch_get_main_queue(), ^{
            [self contextDidSave:notification];
        });
    } else {
        [self.managedObjectContext mergeChangesFromContextDidSaveNotification:notification];
    }
}

由于您的FRC在主要上下文数据发生变化时正在侦听更改,因此FRC将触发其回调,以便您可以在tableview或collectionview中插入/删除/修改记录。

编辑:

听起来您可能没有对后台线程进行任何更改,因为您没有使用后台上下文的performBlock:或私人队列来完成工作:

[backgroundContext performBlock:^{
    // Do your work

    NSError *error = nil;
    BOOL success = [backgroundContext save:&error];

    //  error handling
}];