是否可以在NSFetchedResultsController上使用后台线程进行大量读取操作,以确保UI响应能力? [英] Is it possible to use background thread on NSFetchedResultsController for heavy read operation to ensure UI responsiveness?

查看:33
本文介绍了是否可以在NSFetchedResultsController上使用后台线程进行大量读取操作,以确保UI响应能力?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

Apple在其官方地震示例中向我们展示了如何使用后台线程(通过使用 newBackgroundContext )执行繁重的写入操作-

Apple has shown us how to perform heavy write operation using background thread (by using newBackgroundContext) in their official earth quake example - https://github.com/yccheok/earthquakes-WWDC20

但是,繁重的读取操作呢?(数百万行用于压力测试)

我们还希望我们的应用程序UI在首次启动应用程序时能够响应,并且该应用程序正在从CoreData读取大量数据.

We would also like our app UI to be responsiveness, when we are launching the app for first time, and the app is reading a large amount of data from CoreData.

以下是使用 NSFetchedResultController 的代码段.

let controller = NSFetchedResultsController(fetchRequest: fetchRequest,
                                            managedObjectContext: persistentContainer.viewContext,
                                            sectionNameKeyPath: nil, cacheName: nil)
controller.delegate = fetchedResultsControllerDelegate

// Perform the fetch.
do {
    // This statement tooks some time to complete if you have a lot of rows.
    try controller.performFetch()
} catch {
    fatalError("Unresolved error \(error)")
}


如果有很多行,UI就没有响应

我们尝试使用后台线程执行 controller.performFetch().仍然但不确定为什么,UI仍不响应.我的猜测是,在 NSFetchedResultsController 被占用的UI主线程之后,执行一些耗时的I/O读取操作.


UI is not responsiveness if there are a lot of rows

We try to perform controller.performFetch() using background thread. Still, but not sure why, the UI is still not responsiveness. My guess is that, after NSFetchedResultsController is occupied UI main thread, to perform some time consuming I/O read operation.

let controller = NSFetchedResultsController(fetchRequest: fetchRequest,
                                            managedObjectContext: persistentContainer.viewContext,
                                            sectionNameKeyPath: nil, cacheName: nil)
controller.delegate = fetchedResultsControllerDelegate

DispatchQueue.global(qos: .background).async {
    // Perform the fetch.
    do {
        // This statement tooks some time to complete if you have a lot of rows.
        try controller.performFetch()
    } catch {
        fatalError("Unresolved error \(error)")
    }
}


UI现在正在响应.但是解决方案不正确...

我想,我们也需要将 NSFetchedresultController 放在后台线程下.因此,我们进行以下修改.


UI is responsive now. But the solution is incorrect...

I guess, we need to place NSFetchedresultController under background thread too. Hence, we do the following modification.

let backgroundContext = persistentContainer.newBackgroundContext()
let controller = NSFetchedResultsController(fetchRequest: fetchRequest,
                                            managedObjectContext: backgroundContext,
                                            sectionNameKeyPath: nil, cacheName: nil)
controller.delegate = fetchedResultsControllerDelegate

backgroundContext.perform {
    // Perform the fetch.
    do {
        // This statement tooks some time to complete if you have a lot of rows.
        try controller.performFetch()
    } catch {
        fatalError("Unresolved error \(error)")
    }
}

用户界面在获取过程中具有响应性,并且可以在一段时间后获取并显示数据.

The UI is responsiveness during fetching, and data is able to be fetched and shown after some time.

但是,如果我们使用启动参数进行进一步调查

However, if we investigate further by using the launching argument

-com.apple.CoreData.ConcurrencyDebug 1

在执行 controller.performFetch()后,我们将遇到以下崩溃.

We will experience the following crash after controller.performFetch() finish executed.

CoreData`+[NSManagedObjectContext __Multithreading_Violation_AllThatIsLeftToUsIsHonor__]:

我可以知道,当我们使用 NSFetchedResultController 加载大量数据(根据测试几百万行)时,是否有可能使UI响应? NSFetchedResultController 是否可以在后台线程下运行?

May I know, is it ever possible to make UI responsive, when we are using NSFetchedResultController to load a large amount of data (few millions rows as per testing)? Can NSFetchedResultController ever operated under background thread?

推荐答案

我认为您的问题可能是新控制器分配了 fetchedResultsControllerDelegate .从遇到多线程冲突的地方似乎可以推断出这一点.

I think it is possible that your problem is the assignment of the fetchedResultsControllerDelegate by the new controller. This seems to be inferable from where you encounter the multithreading violation.

根据您提供的代码,尚不清楚委托是哪种对象,但大概是它管理UI并因此在主线程上.您可以看到谁有可能导致线程问题.

From the code you provided, it is not clear what kind of object the delegate is, but presumably it manages the UI and thus is on the main thread. You can see who this can potentially lead to a threading problem.

感谢您在此处 https://stackoverflow.com/a/14710475/427083 上发布此问题的链接一个>.我仍然认为,如果在完成后将FRC分配为表的 datasource ,然后再将 reloadData 分配给表,则该方法对您应该有用.

Thanks for posting a link to this question from my answer here https://stackoverflow.com/a/14710475/427083. I still think that it should work for you if you assign the FRC as the datasource of you table once it is finished, and then reloadData.

在旁注:虽然从工程学的角度来看这个问题有趣且具有挑战性,但我怀疑直接在移动设备上处理数百万条记录的好体系结构.

这篇关于是否可以在NSFetchedResultsController上使用后台线程进行大量读取操作,以确保UI响应能力?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆