【问题标题】:Objective c - fetching core data objects in viewDidLoadObjective c - 在 vi​​ewDidLoad 中获取核心数据对象
【发布时间】:2012-04-24 23:03:28
【问题描述】:

很多时候,我的应用程序中都会出现这样的情况,即我正在推送视图控制器并从核心数据中获取对象以填充 UI。现在我通常在主线程的 viewDidLoad 中执行此操作,我确信有更好的方法来执行此操作,可能在不同的线程上。

如果确实线程是要走的路,我在目标 c 中没有很多线程经验,所以如果有人能给我展示代码示例,我将不胜感激。

而且我知道核心数据不是线程安全的,所以为了安全起见,我应该做任何额外的工作吗?

【问题讨论】:

    标签: iphone objective-c core-data nsfetchedresultscontroller nsthread


    【解决方案1】:

    您可能应该使用 NSFetchedResultsController。它将为您管理批处理,并且只加载您当时需要的内容。它不仅适用于表格视图。您可以在没有单独线程的情况下执行此操作(只要您的数据库不太大,并且您的 fetch 没有需要访问数据库中每条记录的过于复杂的谓词)。

    作为 FRC 的替代方案,或者在需要所有记录的情况下,您可以使用单独的线程,该线程将获取对象,然后将它们呈现给主线程。

    这些是在单个 SO 答案中难以解释的概念,因此如果仍然没有意义,请参阅核心数据并发编程指南。

    或者,如果您想加载所有内容并进行一些控制,您可以执行以下操作。注意:我认为这种双 MOC 模式无论如何都是要走的路,因为无论如何它都更容易做背景。就此而言,如果您使用 UIManagedDocument,无论如何您都可以免费获得其中的大部分内容。

    请注意,这可能需要更长的整体加载时间,但会释放 UI 线程。

    NSManagedObjectContext *workerMoc = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
    workerMoc.persistentStoreCoordinator = psc;
    // The "mainMoc" will be a child of the worker
    NSManagedObjectContext *mainMoc = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
    mainMoc.parentContext = workerMoc;
    

    那么在加载的时候……

    // The actual work will run in the background on the worker queue
    // The "worker" queue will do the fetching and faulting, then pass object IDs
    // to the mainMoc, which will fault its MOs from the parent
    [workerMoc performBlock:^{
        NSFetchRequest *fetchRequest = // Create fetch request
        NSArray *fetchResults = [workerMoc executeFetchRequest:fetchRequest error:0];
        [fetchResults enumerateObjectsUsingBlock:^(NSManagedObject *obj, NSUInteger idx, BOOL *stop) {
            // Probably want to fault the object in before going to mainMoc
            // since that can also take some time...
            // Can also "batch" them in some small number of objects.
            NSManagedObjectID *objectID = obj.objectID;
            [mainMoc performBlock:^{
                NSManagedObject *fetchedObject = [mainMoc objectWithID:objectID];
                // Do something with it now that you are back on the main thread...
            }];
        }          
    }];
    

    【讨论】:

    • 在我的所有应用程序中,我使用一个 moc 并在所有类之间共享,这是否需要创建两个不同的 moc?
    • 您不能从多个线程访问 MOC。所以,你想在一个单独的线程中做任何与数据库相关的事情,你必须使用不同的 MOC。但是,请注意第一句话。在这种情况下,如果您只使用 NSFetchedResultsController,则不需要单独的 MOC,因为它将在主线程上获取。
    • 所以 mainMOC 可以是共享的,我只需要每次都创建 workMoc 对吗?而且我不明白你对 NSFetchedResultsController 的看法,如果我确实使用它,我还需要在单独的线程中使用它吗?也可以阻塞主线程吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多