我正在try 构建一个批量图像下载程序,在这里,图像可以被动态地添加到要下载的队列中,我可以了解下载的进度和完成下载的时间.

通过我的阅读,队列功能似乎是NSOperationQueue,网络功能似乎是NSURLSession,这是我最好的 Select ,但我不知道如何同时使用这两种功能.

我知道我将NSOperation个实例添加到NSOperationQueue,它们就会排队.我似乎创建了一个有NSURLSessionDownloadTask个的下载任务,如果我需要多个任务,我会创建多个,但我不确定如何将两者结合起来.

NSURLSessionDownloadTaskDelegate似乎拥有下载进度和完成通知所需的所有信息,但我还需要能够停止特定下载,停止所有下载,并处理从下载中获得的数据.

推荐答案

你的直觉是正确的.如果发出了很多请求,用4或5的maxConcurrentOperationCount表示NSOperationQueue可能非常有用.如果没有这一点,如果您发出许多请求(例如,50个大图像),在处理慢速网络连接(例如,一些蜂窝连接)时,您可能会遇到超时问题.IMHO表示,操作队列还有其他优势(例如依赖性、分配优先级等),但控制并发程度是关键优势.

如果您使用的是基于completionHandler的请求,那么实现基于操作的解决方案就非常简单(这是典型的并发NSOperation子类实现;有关更多信息,请参阅Concurrency Programming GuideOperation Queues章的Configuring Operations for Concurrent Execution部分).

但是,如果使用基于delegate的实现,事情很快就会变得非常棘手.这是因为NSURLSession有一个可以理解(但令人难以置信地恼火)的特性,任务级别的委托是在会话级别实现的.(考虑一下:两个需要不同处理的不同请求正在对共享会话对象.Egad!调用相同的委托方法.)

在一个操作中包装一个基于委托的NSURLSessionTask是可以做到的(我和其他人肯定已经做到了),但这涉及到一个复杂的过程:让会话对象维护一个字典,用任务操作对象交叉引用任务标识符,让它将这些任务委托方法传递给任务对象,然后让任务对象符合各种NSURLSessionTask委托协议.这是一个相当大的工作量,因为NSURLSession没有在会话上提供maxConcurrentOperationCount风格的特性(更不用说其他NSOperationQueue优点,比如依赖项、完成块等等).

不过,值得指出的是,基于操作的实现在后台会话中有点难以启动.应用程序终止后,您的上传/下载任务将继续正常运行(这是一件好事,这是后台请求中相当重要的行为),但当应用程序重新启动时,操作队列及其所有操作都将消失.因此,在后台会话中,必须使用纯基于委托的NSURLSession实现.

Objective-c相关问答推荐

Objective-C 中的实例变量是否默认设置为 nil?

XCTAssertEqual 不适用于双精度值

如何向 UILabel 添加滚动功能

dispatch_get_global_queue 和 dispatch_queue_create 有什么区别?

获取 Objective-C 类或实例的所有方法

在 UILabel.attributedText *not* 蓝色和 *not* 下划线

获取对 UIApplication 委托的引用

如果安装了应用程序,如何以编程方式判断?

如何正确获取文件大小并将其转换为 Cocoa 中的 MB、GB?

额外的 75 秒从何而来?

Interface Builder 中的 IBOutletCollection 集排序

警告的含义在演示过程中!

如何在 iPhone 中将 NSData 转换为字节数组?

声音在 iPhone 模拟器中不起作用?

在Objective-C中替换字符串中的一个字符

当表格重新出现时,UITableView 不会自动取消 Select 选定的行

通过索引访问 NSMutableDictionary 中的对象

iOS 11 large-title导航栏不折叠

移除所有 CALayer 的子层

xcode 5.1 中的 Arm64 架构