NSAsynchronousFetchRequest - 应该在主线程上显式更新

Posted

技术标签:

【中文标题】NSAsynchronousFetchRequest - 应该在主线程上显式更新【英文标题】:NSAsynchronousFetchRequest - should update be explicitly done on main thread 【发布时间】:2018-10-24 15:41:35 【问题描述】:

我正在创建一个内部有一个完成块的 NSAsynchronousFetchRequest。

我见过各种例子,其中一些包括在主线程上使用调度队列,而另一些则没有。例如,Ray Wenderlich 核心数据手册不会在主线程上调用结果。

执行结果时是否应该返回主线程。起初我以为我必须这样做,但现在我没有。一些明确的清晰度会很棒。

fun exampleFetch(_ completionHandler: @escaping () -> () 
    let fetchRequest = NSFetchRequest<NSDictionary>(entityName: "Example")

    let asyncFetchRequest = NSAsynchronousFetchRequest<NSDictionary>(fetchRequest: fetchRequest)  result in 
         // DispatchQueue.main.async  // is this needed
         completion()
         //
    

    managedContext.performChanges 
        do 
            try self.managedContext.execute(asyncFetchRequest)
         catch let error 
            print("error trying to fetch saving objects:", error.localizedDescription)
        
    

【问题讨论】:

你要么让开发者这样做,要么不这样做。随你(由你决定。您还可以让用户决定他希望所有完成都发生在哪个队列上。例如,CBPeripheralManager 使用委托(不是闭包)让我们决定开发:init(delegate:queue:) @Larme 澄清一下,asyncFetchRequest 的结果是在后台线程上调用的吗? 不知道,待测。它是在不同的队列上运行,还是在同一个队列上运行?例如,如果您在后台队列中启动 fetch,是否会在同一个队列中调用完成? @Larme 不知道我可以测试这个。会调查的,谢谢! if Thread.isMain,或类似的东西。 【参考方案1】:

您不应显式调用主队列上的完成处理程序。让调用者决定如何处理它。如果有的话,请记录将在任意队列上调用完成处理程序。然后调用您的exampleFetch 方法的客户端知道,他们有责任确保在所需的任何队列上处理结果。

这给了客户更多的控制权。

这也防止了很多不必要的线程切换。客户端可以从后台队列调用exampleFetch,它可能希望在后台处理结果。如果您将完成显式放在主队列上,则客户端需要显式切换回后台队列来处理结果。这是两个不必要的队列切换,浪费了主队列的精力。

【讨论】:

感谢您。那么 NSAsynchronousFetchRequest 的结果是在后台线程上执行的,而不是移回主线程?在 RW 书中,他们在 asyncFetchRequest 中重新加载了一个 tableView,并且不会返回主线程 这两种方式都没有记录,但不太可能在主队列上显式调用。快速测试将验证这一点。 是的,这就是为什么我有点困惑,因为它没有记录并假设它在后台,但当我不返回主线程更新 UI 时,它在我的应用程序中运行良好。不知道我可以测试这个!将不得不对此进行调查 - 谢谢 使用调试器。在完成处理程序中放置一个断点。在断点处停止时查看它在哪个线程上。 理论上,我可以在后台上下文中使用普通的获取请求,而不是使用异步请求吗?即它不会阻塞主线程。但是,如果另一个操作需要,那么这是否会阻止后台上下文?

以上是关于NSAsynchronousFetchRequest - 应该在主线程上显式更新的主要内容,如果未能解决你的问题,请参考以下文章