问题描述
制作 NSURLSessionTasks
的串行队列的最佳做法是什么?
What are the best practices for making a serial queue of NSURLSessionTasks
?
在我的情况下,我需要to:
In my case, I need to:
- 获取JSON文件中的URL(
NSURLSessionDataTask
) - 在该URL下载文件(
NSURLSessionDownloadTask
)
- Fetch a URL inside a JSON file (
NSURLSessionDataTask
) - Download the file at that URL (
NSURLSessionDownloadTask
)
以下是我目前的情况:
session = [NSURLSession sharedSession];
//Download the JSON:
NSURLRequest *dataRequest = [NSURLRequest requestWithURL:url];
NSURLSessionDataTask *task =
[session dataTaskWithRequest:dataRequest
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
//Figure out the URL of the file I want to download:
NSJSONSerialization *json = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil];
NSURL *downloadURL = [NSURL urlWithString:[json objectForKey:@"download_url"]];
NSURLSessionDownloadTask *fileDownloadTask =
[session downloadTaskWithRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:playlistURL]]
completionHandler:^(NSURL *location, NSURLResponse *response, NSError *error) {
NSLog(@"completed!");
}];
[fileDownloadTask resume];
}
];
除了在另一个完成中写一个完成块看起来很乱,我收到一个EXC_BAD_ACCESS错误当我打电话给 [fileDownloadTask resume]
...即使 fileDownloadTask
也不是零!
Apart from the fact that writing a completion block within another completion looks messy, I am getting an EXC_BAD_ACCESS error when I call [fileDownloadTask resume]
... Even though fileDownloadTask
is not nil!
那么,最好的排序方法是什么 NSURLSessionTasks
?
So, what is the best of way of sequencing NSURLSessionTasks
?
推荐答案
您需要使用这种最直接的方法:
You need to use this approach which is the most straight forward: https://stackoverflow.com/a/31386206/2308258
或者使用操作队列并使任务相互依赖
Or use an operation queue and make the tasks dependent on each others
========================================== =============================
=======================================================================
关于HTTPMaximumConnectionsPerHost方法
HTTPMaximumConnectionsPerHost仅确保将一个共享连接用于该会议的任务,但并不意味着他们会这样做串行处理。
HTTPMaximumConnectionsPerHost only ensure that one shared connection will be used for the tasks of that session but it does not mean that they will be processed serially.
您可以使用,您会发现在设置HTTPMaximumConnectionsPerHost时,您的任务仍将由NSURLSession同时启动,而不是按照相同的顺序启动。
You can verify that on the network level using http://www.charlesproxy.com/, you wil discover that when setting HTTPMaximumConnectionsPerHost, your tasks will be still be started together at the same time by NSURLSession and not serially as believed.
实验1:
- 使用HTTPMaximumConnectionsPerHost声明NSURLSession为1
- 使用task1:url = download.thinkbroadband.com/20MB.zip
-
使用task2:url = download.thinkbroadband.com/20MB.zip
- Declaring a NSURLSession with HTTPMaximumConnectionsPerHost to 1
- With task1: url = download.thinkbroadband.com/20MB.zip
With task2: url = download.thinkbroadband.com/20MB.zip
- 调用[task1 resume];
- 调用[task2 resume];
结果:调用task1 completionBlock然后调用task2 completionBlock
Result: task1 completionBlock is called then task2 completionBlock is called
如果任务占用相同的数量,可能会按照预期的顺序调用完成块e 但是如果您尝试使用相同的NSURLSession下载两个不同的东西,您会发现NSURLSession没有任何基本的调用顺序,但只完成任何完成。
The completion blocks might be called in the order you expected in case the tasks take the same amount of time however if you try to download two different thing using the same NSURLSession you will discover that NSURLSession does not have any underlying ordering of your calls but only completes whatever finishes first.
实验2:
- 使用HTTPMaximumConnectionsPerHost声明NSURLSession为1
- task1:url = download.thinkbroadband.com/20MB.zip
-
task2:url = download.thinkbroadband.com/10MB.zip(较小的文件)
- 调用[task1 resume];
- 调用[task2]简历];
结果:task2 completionBlock是调用然后调用task1 completionBlock
Result: task2 completionBlock is called then task1 completionBlock is called
总之你需要自己做订单,NSURLSession没有任何关于订购请求的逻辑它只会调用completionBlock即使设置最大数量o,也会先完成任何操作f每个主机的连接数为1
PS:很抱歉我发布的帖子格式没有足够的声誉来发布截图。
PS: Sorry for the format of the post I do not have enough reputation to post screenshots.
这篇关于制作NSURLSessionTasks队列的最佳实践的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!