以下是场景:
我正在编写一个DownloadManager
,它允许用户下载、暂停、取消、全部下载和全部暂停。DownloadManager
是一个单例,使用AFNetworking
下载文件。它有自己的私有托管对象上下文,这样用户就可以自由地使用应用程序的其他部分(通过添加、编辑、删除)核心数据对象。我有一个核心数据实体DownloadInfo
,它存储下载信息,即fileURL
、fileSize
、bytesRead
等。DownloadManager
更新DownloadInfo
中的下载进度(每个文件一个)。
我有一个DownloadManagerViewController
,它使用NSFetchedResultsController
向用户显示下载状态。此下载视图控制器正在使用主托管对象上下文。
现在假设我在下载队列中有20个文件。假设只允许3次并发下载。下载管理器应该下载该文件,并显示下载进度。
问题:
CCD_ 12对象正由CCD_ 13以非常高的速率进行更新。DownloadManagerViewController
(负责显示下载进度)正在使用NSFetchedResultsControllerDelegate
方法更新列表。结果是在主队列中发生了很多事情,应用程序的响应能力非常差。
我该怎么解决这个问题?如何在显示下载进度的同时使应用程序响应?
-
我不知道如何在
DownloadManager
和DownloadManagerViewController
之间通信下载状态。还有其他更好的方法吗? -
出于上述原因,我不想在
DownloadManager
中使用主托管对象上下文。注意,DownloadManager
使用的是异步处理请求的AFNetworking
,但最终DownloadInfo
对象会在主线程中更新(作为回调方法的结果)。也许有一种方法可以在后台线程中处理下载和状态更新操作?但是怎么做呢?我将如何在主线程和后台线程之间进行通信,即我将如何告诉后台线程排队下载另一个文件?
谢谢。
与其观察托管对象上下文的每一次更改,不如考虑为您实际想要更新屏幕的事件实现一个或多个通知。如果通知是从后台线程发布的,请确保在触发任何UI更新之前切换回主线程。
或者,当调用FRC委托方法时,您会收到有关实际更改内容的信息。您可以对此进行分析,筛选出最频繁、最没有意义的更改,并防止它们导致UI更新。
您是否尝试过使用Instruments来查看ViewController中到底发生了什么?时间档案器将告诉您CPU在哪里花费的时间更多,并将帮助您确定问题的根源。如果不知道这一点,我们就无法确切地知道你应该做什么性能调整。
使用Instruments后,如果NSFetchedResultsController
强制对VC进行大量更新,则应考虑不要从CoreData中读取进度。我已经看到,我的许多表或视图在读取CoreData时花费的时间比绘制要多。假设您的问题是CoreData读取,我会尝试从NSMutableDictionary
读取进度,并在下载超过certan阈值时更新UI。