ios - 如何检查dispatch_async是否被提前调用以进行相同的操作

标签 ios iphone multithreading dispatch-async

我遇到了一个问题。我的应用程序从服务器下载图像并显示在 UITableView 中 为了下载图像,我使用 dispatch_async

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    // downloading image from server
    dispatch_async(dispatch_get_main_queue(), ^{
        // update UI for showing downloaded image
    });
});

现在的问题是,如果用户上下滚动速度非常快,那么多个 dispatch_async 会为同一张图片触发。我有图像 ID。有什么方法可以通过图像 ID 检查 dispatch_async 是否为该图像被触发?

最佳答案

您必须设置自己的机制来跟踪是否有任何对该图像的未决请求(例如,由图像 URL 绝对字符串或类似内容键入的字典)。问题是,事情并没有那么简单,因为现在需要更新的单元格可能不同于(或除了)最初请求它的单元格。这很快就会变得丑陋。

但我会退后一步,问问这是根本问题还是更广泛问题的症状。例如,如果用户相对快速地向下滚动到第 100 行。该图像请求是否积压在前 99 行之后?当你处于那种情况时,你描述的问题开​​始变得严重,因为如果你现在在其他 99 张图像完成下载之前快速滚动回到顶部,你将发出获取它们的请求 再次。

但是,如果您更改异步图像检索以取消对不可见单元格的请求,那么这个严重的问题突然变得有点学术化了。此外,您还有一个额外的好处,即用户快速滚动到的第 100 行的图像不会积压在所有其他图像请求之后,因此它显示得非常快。

这意味着您要使用可取消的异步请求。因此,这将建议使用 NSURLSession(如果您必须支持早于 NSURLSession 的操作系统版本,则使用基于委托(delegate)的 NSURLConnection)。此外,这通常会使人倾向于操作队列和子类异步 NSOperation 子类,而不是您的问题建议的 GCD 队列(使它们可取消、异步,并限制并发程度)。然后,您必须实现使用您辛勤创建的所有取消逻辑的代码(例如 UIImageView 类别或您的 UITableViewDataSource 和/或 UITableViewCell 子类使用)。

另外,您要确保使用缓存机制(可能同时用于内存和持久存储)。这样,如果您已经检索到特定图像,当您滚动回该行时,该图像已准备好供您检索,无需再次调用网络。

我知道您曾说过您想自己做这件事,但要正确完成这项工作并非易事。这就是为什么我(和其他人)建议您考虑检查允许您异步检索图像的 UIImageView 类别之一。查看 SDWebImage 提供的 UIImageView 类别或 AFNetworking .如果您正确地使单元格出列,这些单元格将在异步检索图像的同时实现非常灵敏的 UI。他们有效地取消了对重复使用的单元格的请求,从而优先考虑可见单元格。它们还会缓存结果,从而在您向后滚动时获得良好的性能。

关于ios - 如何检查dispatch_async是否被提前调用以进行相同的操作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29132095/

相关文章:

iOS 9 和 XCode 7 dylib 问题

iphone - NSGenericException,NSMutableArray 给出了一些问题

java - 非静态、私有(private)变量值在多线程运行中以某种方式共享/覆盖

ios - 添加自定义 Segues 后 UITableView 在屏幕上的偏移量

ios - 错误是 : variables currently must have an initial value when entered at the top level of the REPL

iPhone 4.0 操作系统, block

c++ - QObject::moveToThread:小部件不能移动到新线程

asp.net - 如果在 ASP.NET 完成其页面处理之前触发后台线程执行,会发生什么情况?

ios - 从带有部分的 SwiftUI 列表中删除 CoreData

ios - 从底部滑动 View 并模糊休息