前言
- DEPRECATED: The NSURLConnection class should no longer be used.
- NSURLSession is the replacement for NSURLConnection
- 从 iOS 9 开始 NSURLConnection 的大部分方法被废弃。
1、NSURLConnection
2、NSURLConnection 同步 GET 请求
// 设置网络接口NSString *urlStr = @"http://192.168.88.200:8080/MJServer/video?type=JSON";// 设置请求路径NSURL *url = [NSURL URLWithString:urlStr];NSURLRequest *urlRequest = [NSURLRequest requestWithURL:url];// 创建同步网络请求NSData *syncNetData = [NSURLConnection sendSynchronousRequest:urlRequest returningResponse:NULL error:NULL];
3、NSURLConnection 同步 POST 请求
// 设置网络接口NSURL *url = [NSURL URLWithString:@"http://192.168.88.200:8080/MJServer/video"];// 创建请求对象NSMutableURLRequest *urlRequest = [NSMutableURLRequest requestWithURL:url];// 设置请求方式,默认为 GET 请求urlRequest.HTTPMethod = @"POST";// 设置请求体(请求参数)urlRequest.HTTPBody = [@"type=JSON" dataUsingEncoding:NSUTF8StringEncoding];// 创建同步网络请求NSData *syncNetData = [NSURLConnection sendSynchronousRequest:urlRequest returningResponse:NULL error:NULL];
4、NSURLConnection 异步 GET 请求
4.1 使用 block 回调方式
// 设置网络接口NSURL *url = [NSURL URLWithString:@"http://192.168.88.200:8080/MJServer/video?type=XML"];// 创建请求对象NSURLRequest *urlRequest = [NSURLRequest requestWithURL:url];// 创建异步网络请求[NSURLConnection sendAsynchronousRequest:urlRequest queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) { if (connectionError == nil && data != nil) { }}];
4.2 使用 协议 方式
// 遵守协议 @property(nonatomic, retain)NSMutableData *asyncNetData;// 设置网络接口NSURL *url = [NSURL URLWithString:@"http://192.168.88.200:8080/MJServer/video?type=XML"];// 创建请求对象NSURLRequest *urlRequest = [NSURLRequest requestWithURL:url];// 创建异步网络请求[NSURLConnection connectionWithRequest:urlRequest delegate:self];// 协议方法// 接收到服务器的响应- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response { // 异步下载数据源初始化 self.asyncNetData = [[NSMutableData alloc] init];}// 接收到服务器数据- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data { // 拼接从服务器下载的数据 [self.asyncNetData appendData:data];}// 服务器的数据加载完毕- (void)connectionDidFinishLoading:(NSURLConnection *)connection { // 处理从服务器下载的数据 self.textView.text = [[NSString alloc] initWithData:self.asyncNetData encoding:NSUTF8StringEncoding];}// 请求错误- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {}
5、NSURLConnection 异步 POST 请求
5.1 使用 block 回调方式
// 设置网络接口NSURL *url = [NSURL URLWithString:@"http://192.168.88.200:8080/MJServer/video"];// 创建请求对象NSMutableURLRequest *urlRequest = [NSMutableURLRequest requestWithURL:url];// 设置请求方式,默认为 GET 请求urlRequest.HTTPMethod = @"POST";// 设置请求体(请求参数)urlRequest.HTTPBody = [@"type=XML" dataUsingEncoding:NSUTF8StringEncoding];// 创建异步网络请求[NSURLConnection sendAsynchronousRequest:urlRequest queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) { if (connectionError == nil && data != nil) { }}];
5.2 使用 协议 方式
// 遵守协议 // 设置网络接口NSURL *url = [NSURL URLWithString:@"http://192.168.88.200:8080/MJServer/video"];// 创建请求对象NSMutableURLRequest *urlRequest = [NSMutableURLRequest requestWithURL:url];// 设置请求方式,默认为 GET 请求urlRequest.HTTPMethod = @"POST";// 设置请求体(请求参数)urlRequest.HTTPBody = [@"type=XML" dataUsingEncoding:NSUTF8StringEncoding];// 创建异步网络请求[NSURLConnection connectionWithRequest:urlRequest delegate:self];// 协议方法// 已经发送请求体- (void)connection:(NSURLConnection *)connection didSendBodyData:(NSInteger)bytesWritten totalBytesWritten:(NSInteger)totalBytesWritten totalBytesExpectedToWrite:(NSInteger)totalBytesExpectedToWrite {}// 接收到服务器的响应- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {}// 接收到服务器数据- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {}// 服务器的数据加载完毕- (void)connectionDidFinishLoading:(NSURLConnection *)connection {}// 请求错误- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {}
6、NSURLConnection 文件下载
6.1 获取文件信息
NSURL *url = [NSURL URLWithString:@"http://192.168.88.200/download/file/minion_02.mp4"];NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];// 使用 HEAD 请求方式request.HTTPMethod = @"HEAD";NSURLResponse *response = nil;NSError *error = nil;// 使用同步请求方式,后续的下载会依赖于此[NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];if (error == nil && response != nil) { // 获取文件大小或名称 NSLog(@"要下载文件的长度 %tu", response.expectedContentLength);}
6.2 使用 GET 数据请求方式下载,文件句柄存储
// 下载文件的总长度@property (nonatomic, assign) long long expectedContentLength;// 当前文件大小@property (nonatomic, assign) long long recvedfileLength;NSURL *url = [NSURL URLWithString:@"http://192.168.88.200/download/file/minion_02.mp4"];NSURLRequest *urlRequest = [NSURLRequest requestWithURL:url];// 遵守协议 [NSURLConnection connectionWithRequest:urlRequest delegate:self];// 协议方法- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response { NSString *documentsPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)[0] stringByAppendingPathComponent:@"321.mp4"]; // 如果文件不存在,方法不会出错 [[NSFileManager defaultManager] removeItemAtPath:documentsPath error:NULL]; // 获取数据总大小 self.expectedContentLength = response.expectedContentLength; self.recvedfileLength = 0;}- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data { // 将从服务器下载的数据直接写入文件 [self writeToFile:data]; // 计算当前数据下载完成的大小 self.recvedfileLength += data.length; // 计算下载进度 float progress = (float)self.recvedfileLength / self.expectedContentLength;}- (void)connectionDidFinishLoading:(NSURLConnection *)connection {}- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {}// 将数据写入文件- (void)writeToFile:(NSData *)data { /* NSFileManager:文件管理器,文件复制,删除,是否存在...操作,类似于在 Finder 中进行的操作 NSFileHandle :文件 "句柄(指针)" Handle 操纵杆,凡事看到 Handle 单词,表示对前面一个名词(File)的操作, 对一个文件进行独立的操作。 */ NSString *documentsPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)[0] stringByAppendingPathComponent:@"321.mp4"]; // 打开文件,如果文件不存在,fp == nil NSFileHandle *fp = [NSFileHandle fileHandleForWritingAtPath:documentsPath]; // 如果文件不存在 if (fp == nil) { // 将数据直接写入文件 [data writeToFile:documentsPath atomically:YES]; } else { // 将文件指针移动到文件末尾 [fp seekToEndOfFile]; // 写入数据 [fp writeData:data]; // 关闭文件,C 语言中有一个默认的约定,凡事打开文件,都必须关闭 [fp closeFile]; }}
6.3 使用 GET 数据请求方式下载,文件输出流存储
// 下载文件的总长度@property (nonatomic, assign) long long expectedContentLength;// 当前文件大小@property (nonatomic, assign) long long recvedfileLength;// 输出数据流@property (nonatomic, strong) NSOutputStream *fileStream;NSURL *url = [NSURL URLWithString:@"http://192.168.88.200/download/file/minion_02.mp4"];NSURLRequest *urlRequest = [NSURLRequest requestWithURL:url];// 遵守协议 [NSURLConnection connectionWithRequest:urlRequest delegate:self];// 协议方法- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response { NSString *documentsPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)[0] stringByAppendingPathComponent:@"312.mp4"]; // 如果文件不存在,方法不会出错 [[NSFileManager defaultManager] removeItemAtPath:documentsPath error:NULL]; // 以拼接的方式实例化文件流 self.fileStream = [[NSOutputStream alloc] initToFileAtPath:documentsPath append:YES]; // 打开文件流 [self.fileStream open]; // 获取数据总大小 self.expectedContentLength = response.expectedContentLength; self.recvedfileLength = 0;}- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data { // 将数据的 "字节"一次性写入文件流,并且指定数据长度 [self.fileStream write:data.bytes maxLength:data.length]; // 计算当前数据下载完成的大小 self.recvedfileLength += data.length; // 计算下载进度 float progress = (float)self.recvedfileLength / self.expectedContentLength;}- (void)connectionDidFinishLoading:(NSURLConnection *)connection { // 关闭文件流 [self.fileStream close];}- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error { // 关闭文件流 [self.fileStream close];}
6.4 使用 专用下载 方式
NSURL *url = [NSURL URLWithString:@"http://192.168.88.200/download/file/minion_01.mp4"];NSURLRequest *urlRequest = [NSURLRequest requestWithURL:url];// 遵守协议 [NSURLConnection connectionWithRequest:urlRequest delegate:self];// 协议方法- (void)connection:(NSURLConnection *)connection didWriteData:(long long)bytesWritten totalBytesWritten:(long long)totalBytesWritten expectedTotalBytes:(long long)expectedTotalBytes { /* 下载进度: bytesWritten 本次下载子节数 totalBytesWritten 已经下载字节数 expectedTotalBytes 总下载字节数(文件总大小) */ float progress = (float)totalBytesWritten / expectedTotalBytes; NSLog(@"%f", progress);}- (void)connectionDidFinishDownloading:(NSURLConnection *)connection destinationURL:(NSURL *) destinationURL { /* destinationURL 下载保存的路径,下载完成之后,找不到下载的文件。 */ NSLog(@"%@", destinationURL);}
6.5 断点续传下载
// 下载文件的总长度@property (nonatomic, assign) long long expectedContentLength;// 当前文件大小@property (nonatomic, assign) long long recvedfileLength;// 输出数据流@property (nonatomic, strong) NSOutputStream *fileStream;// 目标目录@property (nonatomic, copy) NSString *targetPath;@property (nonatomic, strong) NSURLConnection *conn;NSURL *url = [NSURL URLWithString:@"http://192.168.88.200/download/file/minion_02.mp4"];// 检查服务器上的文件信息[self checkServerFileInfoWithURL:url];// 检查本地文件信息long long fileSize = [self checkLocalFileInfo];// 文件已经下载到本地if (fileSize == self.expectedContentLength) { return;}// 根据本地文件的长度,从对应 "偏移" 位置开始下载[self downloadWithURL:url offset:fileSize];// 检查服务器上的文件信息- (void)checkServerFileInfoWithURL:(NSURL *)url { NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; request.HTTPMethod = @"HEAD"; NSURLResponse *response = nil; NSError *error = nil; // 发送同步方法 [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error]; if (error == nil && response != nil) { // 文件大小 self.expectedContentLength = response.expectedContentLength; // 文件名,保存到临时文件夹 self.targetPath = [NSTemporaryDirectory() stringByAppendingPathComponent:response.suggestedFilename]; }}// 检查本地文件信息- (long long)checkLocalFileInfo { long long fileSize = 0; // 检查本地是否存在文件 if ([[NSFileManager defaultManager] fileExistsAtPath:self.targetPath]) { NSDictionary *dict = [[NSFileManager defaultManager] attributesOfItemAtPath:self.targetPath error:NULL]; // 获取文件大小 fileSize = [dict fileSize]; } // 判断是否比服务器的文件大 if (fileSize > self.expectedContentLength) { // 删除文件 [[NSFileManager defaultManager] removeItemAtPath:self.targetPath error:NULL]; fileSize = 0; } return fileSize;}// 从断点处开始下载- (void)downloadWithURL:(NSURL *)url offset:(long long)offset { // 记录本地文件大小 self.recvedfileLength = offset; NSMutableURLRequest *urlRequest = [NSMutableURLRequest requestWithURL:url cachePolicy:1 timeoutInterval:15]; // 一旦设置了 Range,response 的状态码会变成 206 [urlRequest setValue:[NSString stringWithFormat:@"bytes=%lld-", offset] forHTTPHeaderField:@"Range"]; // 遵守协议 self.conn = [NSURLConnection connectionWithRequest:urlRequest delegate:self]; [self.conn start];}// 暂停下载- (void)pause1 { [self.conn cancel];}// 协议方法- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response { // 以拼接的方式实例化文件流 self.fileStream = [[NSOutputStream alloc] initToFileAtPath:self.targetPath append:YES]; [self.fileStream open];}- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data { // 将数据的 "字节"一次性写入文件流,并且指定数据长度 [self.fileStream write:data.bytes maxLength:data.length]; // 计算当前数据下载完成的大小 self.recvedfileLength += data.length; // 计算下载进度 float progress = (float)self.recvedfileLength / self.expectedContentLength;}- (void)connectionDidFinishLoading:(NSURLConnection *)connection { [self.fileStream close];}- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error { // 关闭文件流 [self.fileStream close];}
6.6 异步下载
// 下载文件的总长度@property (nonatomic, assign) long long expectedContentLength;// 当前文件大小@property (nonatomic, assign) long long recvedfileLength;// 输出数据流@property (nonatomic, strong) NSOutputStream *fileStream;dispatch_async(dispatch_get_global_queue(0, 0), ^{ NSURL *url = [NSURL URLWithString:@"http://192.168.88.200/download/file/minion_02.mp4"]; NSURLRequest *urlRequest = [NSURLRequest requestWithURL:url]; // 遵守协议 [NSURLConnection connectionWithRequest:urlRequest delegate:self]; // 启动运行循环 CFRunLoopRun();});// 协议方法- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response { NSString *documentsPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)[0] stringByAppendingPathComponent:@"312.mp4"]; // 如果文件不存在,方法不会出错 [[NSFileManager defaultManager] removeItemAtPath:documentsPath error:NULL]; // 以拼接的方式实例化文件流 self.fileStream = [[NSOutputStream alloc] initToFileAtPath:documentsPath append:YES]; // 打开文件流 [self.fileStream open]; // 获取数据总大小 self.expectedContentLength = response.expectedContentLength; self.recvedfileLength = 0;}- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data { // 将数据的 "字节"一次性写入文件流,并且指定数据长度 [self.fileStream write:data.bytes maxLength:data.length]; // 计算当前数据下载完成的大小 self.recvedfileLength += data.length; // 计算下载进度 float progress = (float)self.recvedfileLength / self.expectedContentLength;} - (void)connectionDidFinishLoading:(NSURLConnection *)connection { // 关闭文件流 [self.fileStream close];}- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error { // 关闭文件流 [self.fileStream close];}
7、NSURLConnection 下载单例封装
7.1 QDownloaderOperation.h
@interface QDownloaderOperation : NSOperation/// 类方法+ (instancetype)downloaderWithURL:(NSURL *)url progress:(void (^)(float progress))progress successed:(void (^)(NSString *targetPath))successed failed:(void (^)(NSError *error))failed;/// 暂停当前下载- (void)pauseDownload;/// 取消当前下载- (void)cancelDownload;@end
7.2 QDownloaderOperation.m
@interface QDownloaderOperation () /// 下载文件总长度@property (nonatomic, assign) long long expectedContentLength;/// 已下载文件大小@property (nonatomic, assign) long long recvedfileLength;/// 下载目标目录@property (nonatomic, copy) NSString *targetPath;/// 下载文件输出数据流@property (nonatomic, strong) NSOutputStream *fileStream;/// block 属性@property (nonatomic, copy) void (^progressBlock)(float);@property (nonatomic, copy) void (^successedBlock)(NSString *);@property (nonatomic, copy) void (^failedBlock)(NSError *);/// 网络连接属性@property (nonatomic, strong) NSURLConnection *conn;@property (nonatomic, strong) NSURL *downloadURL;@end+ (instancetype)downloaderWithURL:(NSURL *)url progress:(void (^)(float))progress successed:(void (^)(NSString *))successed failed:(void (^)(NSError *))failed { QDownloaderOperation *downloader = [[self alloc] init]; downloader.progressBlock = progress; downloader.successedBlock = successed; downloader.failedBlock = failed; downloader.downloadURL = url; return downloader;}- (void)main { @autoreleasepool { // 检查服务器上的文件信息 [self checkServerFileInfoWithURL:self.downloadURL]; if (self.isCancelled) return; // 检查本地文件信息 long long fileSize = [self checkLocalFileInfo]; if (fileSize == self.expectedContentLength) { // 下载完成的回调 if (self.successedBlock) { dispatch_async(dispatch_get_main_queue(), ^{ self.successedBlock(self.targetPath); }); // 下载进度的回调 if (self.progressBlock) { self.progressBlock(1.0); } } return; } // 根据本地文件的长度,从对应 "偏移" 位置开始下载 [self downloadWithURL:self.downloadURL offset:fileSize]; }}- (void)pauseDownload { // 取消一个请求,调用此方法后,连接不在调用代理方法 [self.conn cancel];}- (void)cancelDownload { [self.conn cancel]; [[NSFileManager defaultManager] removeItemAtPath:self.targetPath error:NULL];}/// 检查服务器上的文件信息- (void)checkServerFileInfoWithURL:(NSURL *)url { NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; request.HTTPMethod = @"HEAD"; NSURLResponse *response = nil; NSError *error = nil; // 发送同步方法 [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error]; if (error == nil && response != nil) { // 文件大小 self.expectedContentLength = response.expectedContentLength; // 文件名 self.targetPath = [NSTemporaryDirectory() stringByAppendingPathComponent:response.suggestedFilename]; }}/// 检查本地文件信息- (long long)checkLocalFileInfo { long long fileSize = 0; // 检查本地是否存在文件 if ([[NSFileManager defaultManager] fileExistsAtPath:self.targetPath]) { NSDictionary *dict = [[NSFileManager defaultManager] attributesOfItemAtPath:self.targetPath error:NULL]; // 获取文件大小 fileSize = [dict fileSize]; } // 判断是否比服务器的文件大 if (fileSize > self.expectedContentLength) { // 删除文件 [[NSFileManager defaultManager] removeItemAtPath:self.targetPath error:NULL]; fileSize = 0; } return fileSize;}/// 从断点处开始下载- (void)downloadWithURL:(NSURL *)url offset:(long long)offset { // 记录本地文件大小 self.recvedfileLength = offset; NSMutableURLRequest *urlRequest = [NSMutableURLRequest requestWithURL:url cachePolicy:1 timeoutInterval:15]; // 一旦设置了 Range,response 的状态码会变成 206 [urlRequest setValue:[NSString stringWithFormat:@"bytes=%lld-", offset] forHTTPHeaderField:@"Range"]; // 遵守协议 self.conn = [NSURLConnection connectionWithRequest:urlRequest delegate:self]; [self.conn start]; // 开启子线程运行循环 CFRunLoopRun();}/// 协议方法- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response { // 以拼接的方式实例化文件流 self.fileStream = [[NSOutputStream alloc] initToFileAtPath:self.targetPath append:YES]; // 打开文件流 [self.fileStream open];}- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data { // 将数据的 "字节" 一次性写入文件流,并且指定数据长度 [self.fileStream write:data.bytes maxLength:data.length]; // 计算当前数据下载完成的大小 self.recvedfileLength += data.length; // 计算下载进度 float progress = (float)self.recvedfileLength / self.expectedContentLength; // 进度的回调 if (self.progressBlock) { self.progressBlock(progress); }}- (void)connectionDidFinishLoading:(NSURLConnection *)connection { // 关闭文件流 [self.fileStream close]; // 完成的回调 if (self.successedBlock) { // 主线程回调 dispatch_async(dispatch_get_main_queue(), ^{ self.successedBlock(self.targetPath); }); }}- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error { // 关闭文件流 [self.fileStream close]; // 失败的回调 if (self.failedBlock) { self.failedBlock(error); }}
7.3 QDownloaderManager.h
@interface QDownloaderManager : NSObject/// 单例+ (instancetype)sharedManager;/// 开始下载- (void)downloadWithURL:(NSURL *)url progress:(void (^)(float progress))progress successed:(void (^)(NSString *targetPath))successed failed:(void (^)(NSError *error))failed;/// 暂停下载- (void)pauseWithURL:(NSURL *)url;/// 取消下载- (void)cancelWithURL:(NSURL *)url;@end
7.4 QDownloaderManager.m
@interface QDownloaderManager ()/// 下载操作缓冲池@property (nonatomic, strong) NSMutableDictionary *downloadCache;/// 下载操作队列@property (nonatomic, strong) NSOperationQueue *downloadQueue;@end+ (instancetype)sharedManager { static id instance; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ instance = [[self alloc] init]; }); return instance;}- (void)downloadWithURL:(NSURL *)url progress:(void (^)(float))progress successed:(void (^)(NSString *))successed failed:(void (^)(NSError *))failed { // 检查缓冲池中是否有下载,如果有,直接返回 if (self.downloadCache[url.absoluteString] != nil) { NSLog(@"正在在玩命下载中..."); return; } QDownloaderOperation *downloader = [QDownloaderOperation downloaderWithURL:url progress:progress successed:^(NSString *targetPath) { // 删除下载操作 [self.downloadCache removeObjectForKey:url.absoluteString]; if (successed != nil) { successed(targetPath); } } failed:^(NSError *error) { [self.downloadCache removeObjectForKey:url.absoluteString]; if (failed != nil) { failed(error); } }]; // 添加到缓冲池 [self.downloadCache setObject:downloader forKey:url.absoluteString]; // 添加到队列 [self.downloadQueue addOperation:downloader];}- (void)pauseWithURL:(NSURL *)url { // 判断缓冲池中是否有对应的下载操作 QDownloaderOperation *downloader = self.downloadCache[url.absoluteString]; if (downloader != nil) { // 暂停 downloader 内部的 NSURLConnection [downloader pauseDownload]; // 给操作发送取消消息 NSOperation [downloader cancel]; // 从缓冲池中清除 [self.downloadCache removeObjectForKey:url.absoluteString]; }}- (void)cancelWithURL:(NSURL *)url { // 判断缓冲池中是否有对应的下载操作 QDownloaderOperation *downloader = self.downloadCache[url.absoluteString]; if (downloader != nil) { // 取消 downloader 内部的 NSURLConnection [downloader cancelDownload]; // 给操作发送取消消息 NSOperation [downloader cancel]; // 从缓冲池中清除 [self.downloadCache removeObjectForKey:url.absoluteString]; }}/// 懒加载- (NSMutableDictionary *)downloadCache { if (_downloadCache == nil) { _downloadCache = [NSMutableDictionary dictionary]; } return _downloadCache;}- (NSOperationQueue *)downloadQueue { if (_downloadQueue == nil) { _downloadQueue = [[NSOperationQueue alloc] init]; // 设置最大并发数 _downloadQueue.maxConcurrentOperationCount = 5; } return _downloadQueue;}
7.5 ViewController.m
// 下载进度@property (weak, nonatomic) IBOutlet UIProgressView *progressView;@property (nonatomic, strong) NSURL *url;// 开始下载NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/resources/videos/minion_01.mp4"];self.url = url;[[QDownloaderManager sharedManager] downloadWithURL:url progress:^(float progress) { dispatch_async(dispatch_get_main_queue(), ^{ self.progressView.progress = progress; }); } successed:^(NSString *targetPath) { NSLog(@"%@", targetPath); } failed:^(NSError *error) { NSLog(@"%@", error);}];// 暂停下载[[QDownloaderManager sharedManager] pauseWithURL:self.url];// 取消下载[[QDownloaderManager sharedManager] cancelWithURL:self.url];