【问题标题】:Magical Record - fetch in main thread block ui, in background return nilMagical Record - 在主线程块 ui 中获取,在后台返回 nil
【发布时间】:2014-01-28 10:07:08
【问题描述】:

我是 Magical Record 的新手,但已经看过一些关于 stackoverflow 的问题,但找不到我的问题的答案。

我必须使用这种类型的结构找到带有谓词的项目:

NSArray *result = [MOSomeItems MR_findAllWithPredicate:predicate];

在主线程结果返回一些值,但 UI 卡住了。

使用此构造时,结果返回 nil 值:

dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
NSArray *result = [MOSomeItems MR_findAllWithPredicate:predicate];
});

在后台获取数据的最佳做法是什么?

【问题讨论】:

    标签: ios core-data freeze magicalrecord background-thread


    【解决方案1】:

    您需要使用带有私有队列的上下文,然后使用获取的 ID 从主上下文中提取结果。

    // Create a child context of our main context
    NSManagedObjectContext *privateContext = [NSManagedObjectContext MR_context];
    // When using private contexts you must execute the core data code in it's private queue using performBlock: or performBlockAndWait:
    [privateContext performBlock:^{
      // Execute your fetch
      NSArray *privateObjects = [MOSomeItems MR_findAllWithPredicate:predicate inContext:privateContext];
      // Convert your fetched objects into object IDs which can be pulled out of the main context
      NSArray *privateObjectIDs = [privateObjects valueForKey:@"objectID"];
      // Return to our main thread
      dispatch_async(dispatch_get_main_queue(), ^{
        // Create a new predicate to use to pull our objects out
        NSPredicate *mainPredicate = [NSPredicate predicateWithFormat:@"self IN %@", privateObjectIDs];
        // Execute your fetch
        NSArray *finalResults = [MOSomeItems MR_findAllWithPredicate:mainPredicate];
        // Now you can use finalResults however you need from the main thread
      });
    }];
    

    您还可以使用 -[NSManagedObjectContext objectWithID:] 方法提取对象,将 privateObjectIDs 数组中的每个对象作为参数传递,但这种方法更短。我还建议您考虑创建一个提取请求(MagicalRecord 有一个 MR_fetchAllWithPredicate: 方法),设置批量大小并手动执行提取。这将允许 Core Data 在返回数组的幕后以块的形式提取数据,以防止线程阻塞。

    希望有帮助!

    【讨论】:

    • 谢谢詹姆斯理查德!我试过你的版本,它对我有帮助。你能说,我是对的吗,我设置了这样的批量大小:request.fetchLimit = 20;?谢谢!
    • 很高兴它有帮助。 fetchLimit 属性将限制您的整个结果集,因此您只能返回 20 个对象。您想使用 result.fetchBatchSize 批处理所有对象。 :)
    • @JamesRichard,感谢您的出色回答。我只是想知道,是否有任何处理错误。
    • 不需要加__block吗?
    • 您好,当我使用复合谓词时,您能帮忙吗?
    猜你喜欢
    • 2016-01-18
    • 1970-01-01
    • 2013-06-22
    • 1970-01-01
    • 1970-01-01
    • 2019-06-26
    • 1970-01-01
    • 1970-01-01
    • 2019-08-18
    相关资源
    最近更新 更多