NSURLSessionDownloadDelegate
NSURLSessionDownloadDelegateのURLSession:downloadTask:didWriteData:totalBytesWritten:totalBytesExpectedToWrite:
でダウンロードの進捗が取れます。
対象のtaskが引数で渡ってくるので、taskとblockの組み合わせをDictionaryで持っとけばいいです。
SessionTaskManager
SessionTaskManagerなるクラスを作って、[NSURLConnection sendSynchronousRequest:returningResponse:error:]
みたいに手軽に非同期リクエストを投げつつ進捗を取れるようにしてみます。
ほんとはもちろんcompletionブロックとか要るし、progress blockが溜まっていく一方なのでまずいですが、ごちゃごちゃするのでここでは省略しますネ
SessionTaskManager.h
@interface SessionTaskManager : NSObject
- (NSURLSessionTask *)executeRequest:(NSURLRequest *)request progress:(void (^)(int64_t doneBytes, int64_t totalBytes))progress;
@end
SessionTaskManager.m
#import "SessionTaskManager.h"
@interface SessionTaskManager ()<NSURLSessionDownloadDelegate>
@property NSURLSession* session;
@property NSMutableDictionary* progressBlockMap;
@end
@implementation SessionTaskManager
- (instancetype)init
{
self = [super init];
if (self) {
_session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]delegate:self delegateQueue:[NSOperationQueue mainQueue]];
_progressBlockMap = [NSMutableDictionary dictionary];
}
return self;
}
- (NSURLSessionTask *)sendRequest:(NSURLRequest *)request progress:(void (^)(int64_t, int64_t))progress
{
NSURLSessionTask* task = [_session downloadTaskWithRequest:request];
//NSURLSessionTaskはNSCopying準拠してるのでkeyに使える
[_progressBlockMap setObject:[progress copy] forKey:task];
[task resume];
return task;
}
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite
{
void (^progress)(int64_t, int64_t) = _progressBlockMap[downloadTask];
progress(totalBytesWritten, totalBytesExpectedToWrite);
}
@end
NSURLSessionManagerはcancelとかが柔軟にできてよいですね。