【问题标题】:NSAsynchronousFetchRequest - should update be explicitly done on main threadNSAsynchronousFetchRequest - 应该在主线程上显式更新
【发布时间】: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,或类似的东西。

标签: ios swift


【解决方案1】:

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

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

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

【讨论】:

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