私は新しい NSURLSession API を使用しており、ユーザーがファイルをダウンロードできるようにしています。実行する同時ダウンロード数を NSURLSession に伝えたいのですが、それを行う方法がわかりません。ダウンロード タスクを自分で管理することは避けたいと思います。システムに許可する数をシステムに伝えることができれば、アプリが実行されていないときにバックグラウンド ダウンロードをキューに入れるのにも適しています。これを行う方法はありますか?
2 に答える
NSURLSessionConfiguration
プロパティでオブジェクトに設定できHTTPMaximumConnectionsPerHost
ます。
このタイムアウトの回避策を見つけました。
デバイスで低速接続シミュレーションを使用してファイルをダウンロードしようとしました (設定 -> 開発者 -> ネットワーク リンク コンディショナー -> プロファイルの選択 -> 3G -> 有効化)。
ここに私のサンプルコードがあります:
- (void) methodForNSURLSession{
NSURLSessionConfiguration *sessionConfig = [NSURLSessionConfiguration defaultSessionConfiguration];
_tasksArray = [[NSMutableArray alloc] init];
sessionConfig.HTTPMaximumConnectionsPerHost = 3;
sessionConfig.timeoutIntervalForResource = 120;
sessionConfig.timeoutIntervalForRequest = 120;
NSURLSession* session = [NSURLSession sessionWithConfiguration:sessionConfig delegate:self delegateQueue:nil];
// data tasks
[self createDownloadTasksWithSession:session];
}
- (void) createDownloadTasksWithSession:(NSURLSession *)session{
for (int i = 0; i < 100; i++) {
NSURLSessionDownloadTask *sessionDownloadTask = [session downloadTaskWithURL: [NSURL URLWithString:@"https://discussions.apple.com/servlet/JiveServlet/showImage/2-20930244-204399/iPhone%2B5%2BProblem2.jpg"]];
[_tasksArray addObject:sessionDownloadTask];
[sessionDownloadTask addObserver:self forKeyPath:@"countOfBytesReceived" options:NSKeyValueObservingOptionOld context:nil];
[sessionDownloadTask resume];
}
}
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context{
if([[change objectForKey:@"old"] integerValue] == 0){
NSLog(@"task %d: started", [_tasksArray indexOfObject: object]);
}
}
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error{
if (!error) {
NSLog(@"task %d: finished!", [_tasksArray indexOfObject:task]);
} else if (error.code == NSURLErrorTimedOut) {
NSLog(@"task %d: timed out!", [_tasksArray indexOfObject:task]);
}
}
そして私の出力:
2014-01-10 10:38:48.769 TestApplication[2442:1803] task 1: started
2014-01-10 10:38:49.517 TestApplication[2442:1803] task 2: started
2014-01-10 10:38:50.273 TestApplication[2442:4b03] task 0: started
2014-01-10 10:40:11.794 TestApplication[2442:5003] task 2: finished!
2014-01-10 10:40:13.924 TestApplication[2442:1803] task 3: started
2014-01-10 10:40:26.221 TestApplication[2442:1d0f] task 1: finished!
2014-01-10 10:40:28.487 TestApplication[2442:1d0f] task 4: started
2014-01-10 10:40:43.007 TestApplication[2442:440f] task 5: timed out!
2014-01-10 10:40:43.009 TestApplication[2442:440f] task 6: timed out!
2014-01-10 10:40:43.011 TestApplication[2442:440f] task 7: timed out!
...
ご覧のとおり、開始されたタスクは 2 分後にタイムアウトします
timeoutIntervalForResource
と timeoutIntervalForRequest パラメータを使用しましたが、両方を 0 に設定すると、タイムアウトなしでダウンロードされます。でも、電池切れなので仕方ないと思います。10分くらいが妥当かなと思います。ただし、両方のパラメーターを同じ値に設定する必要があります。
アップルのドキュメント:
timeoutIntervalForRequest
- 追加データを待機するときに使用するタイムアウト間隔。timeoutIntervalForResource
- リソース要求に許可される最大時間 (1 つのリソースに対するすべてのタスクのタイムアウト)
奇妙なことに気付きました: と を設定した場合timeoutIntervalForResource = 60
、timeoutIntervalForRequest = 30
タスクは 30 秒後にタイムアウトします! しかし、それらのほとんどは起動さえしません!
timeoutIntervalForRequest
タスクが再開されたときに開始されたタイマーのように見えます。その場合、すべてのタスクを同時に再開し、各タスクのタイムアウトはリソース タイムアウトとして設定する必要があります。
また、ダウンロード タスクを使用したバックグラウンド セッションに関する優れたデモを使用して、wwdc13 705 セッションにアドバイスすることもできます。