标签:
下载的一些用法
①对于小文件,可以直接下载,无需断点下载等处理。
1 -(void)clickDownBtn{
2 NSURL *url = [NSURL URLWithString:@"https://picjumbo.imgix.net/HNCK8461.jpg?q=40&w=1650&sharp=30"];
3 if (self.imgView.image == nil) {
4 [self downLoad:url];
5 }
6 }
7
8 //下载过程
9 -(void)downLoad:(NSURL *)url{
10 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
11 NSData *imgData = [NSData dataWithContentsOfURL:url];
12 UIImage *img = [UIImage imageWithData:imgData];
13 if (imgData != nil) {
14 dispatch_sync(dispatch_get_main_queue(), ^{
15 self.imgView.image = img;
16 });
17 }
18 });
19 }
需要注意的是,多线程中,数据处理是在子线程,UI更新是在主线程。若处理数据时没有在子线程中进行,那么会发生线程阻塞、界面卡死的情况。如下载图片时,
-(void)downLoad:(NSURL *)url{
//数据处理(NSData)是在主线程中进行,所以会卡死
//况且这种写法是没有意义的,本来就在主线程,就无需再跳往主线程更新UI
NSData *imgData = [NSData dataWithContentsOfURL:url];
UIImage *img = [UIImage imageWithData:imgData];
if (imgData != nil) {
dispatch_sync(dispatch_get_main_queue(), ^{
self.imgView.image = img;
});
}
}
正确的方法是,先开辟子线程,然后在主线程更新UI。
开辟子线程
-(void)downLoad:(NSURL *)url{
//开辟子线程
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
//操作
});
}
async是异步,sync是同步
②而对于大文件,则可以使用NSURLSession实现暂停、断点下载等操作。如下:
监听下载进度,需要实现代理NSURLSessionDownloadDelegate,在这代理中常用的有3个方法
/** 下载完毕会调用,location为文件临时地址 */
-(void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location{
}
/**
* 每次写入沙盒完毕后调用,在这里可以设置进度条数据等操作
* totalBytesWritten/totalBytesExpectedToWrite,这两个用来监视下载进度
*
* @param bytesWritten 这次写入的大小
* @param totalBytesWritten 已经写入沙盒的大小
* @param totalBytesExpectedToWrite 文件总大小
*/
-(void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten
totalBytesWritten:(int64_t)totalBytesWritten
totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite{
}
/** 恢复下载时使用 */
-(void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didResumeAtOffset:(int64_t)fileOffset expectedTotalBytes:(int64_t)expectedTotalBytes{
}
示例代码如下,在.m中
/** 展示进度的label */
@property(nonatomic,strong) UILabel *progressLabel;
/** 进度动画 */
@property(nonatomic,strong) UIProgressView *progressView;
/** 下载按钮 */
@property(nonatomic,strong) UIButton *downBtn;
/** 下载任务 */
@property(nonatomic,strong) NSURLSessionDownloadTask *downLoadTask;
/** 缓存数据 */
@property(nonatomic,strong) NSData *tempData;
/** session */
@property(nonatomic,strong) NSURLSession *session;
session的懒加载为
-(NSURLSession *)session{
if (!_session) {
NSURLSessionConfiguration *cfg = [NSURLSessionConfiguration defaultSessionConfiguration];
_session = [NSURLSession sessionWithConfiguration:cfg delegate:self delegateQueue:[NSOperationQueue mainQueue]];
}
return _session;
}
按钮点击事件如下:
//点击下载按钮
-(void)clickDownBtn{
self.downBtn.selected = !self.downBtn.selected;
if (nil == self.downLoadTask) {
if (self.tempData) {
[self goOnDownload]; //继续下载
} else { //从0开始下载
[self startDownload];
}
} else {
[self pauseDownload];
}
}
/** 开始下载 */
-(void)startDownload{
NSURL *url = [NSURL URLWithString:@"http://11.gxdx2.crsky.com/201501/apkok-v3.0.zip"];
//创建任务
self.downLoadTask = [self.session downloadTaskWithURL:url];
//开始任务
[self.downLoadTask resume];
}
/** 暂停下载 */
-(void)pauseDownload{
//防止循环引用
__weak typeof(self) weakSelf = self;
[self.downLoadTask cancelByProducingResumeData:^(NSData *resumeData) {
//resumeData包含了继续下载的开始位置和url
weakSelf.tempData = resumeData;
weakSelf.downLoadTask = nil;
}];
}
/** 恢复下载 */
-(void)goOnDownload{
//传入上次暂停下载返回的数据,即可恢复下载
self.downLoadTask = [self.session downloadTaskWithResumeData:self.tempData];
[self.downLoadTask resume];
self.tempData = nil;
}
实现2个代理方法,第3个暂时用不到
/** 下载完毕会调用,location为文件临时地址 */
-(void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location{
//选择下载文件路径,文件只能下载到该程序的目录中
//下边为下载到Documents文件夹,若将NSDocumentDirectory换为NSCachesDirectory,则会下载到Cache文件夹
NSString *caches = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
//response.suggestedFilename建议使用的文件名,一般跟服务器端的名称一致
NSString *file = [caches stringByAppendingPathComponent:downloadTask.response.suggestedFilename];
//将临时文件复制或剪切到caches文件夹
NSFileManager *fileManager = [NSFileManager defaultManager];
//AtPath : 剪切前的文件路径
//toPath : 剪切后的文件路径
//因为文件都是下载到临时文件夹,下载完成后会删除,所以必须移位置
[fileManager moveItemAtPath:location.path toPath:file error:nil];
// 提示下载完成
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"下载完成" message:downloadTask.response.suggestedFilename delegate:self cancelButtonTitle:nil otherButtonTitles: nil];
[alert show];
[self performSelector:@selector(dismissAlert:) withObject:alert afterDelay:2];
//将下载按钮置灰
self.downBtn.selected = NO;
self.downBtn.enabled = NO;
}
/**
* 每次写入沙盒完毕后调用,在这里可以设置进度条数据等操作
* totalBytesWritten/totalBytesExpectedToWrite,这两个用来监视下载进度
*
* @param bytesWritten 这次写入的大小
* @param totalBytesWritten 已经写入沙盒的大小
* @param totalBytesExpectedToWrite 文件总大小
*/
-(void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten
totalBytesWritten:(int64_t)totalBytesWritten
totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite{
//注意该处的progress,等号右边必须强制转换为double型,进度条才有动画效果,否则只有在下载完成后才有
self.progressView.progress = (float)totalBytesWritten/totalBytesExpectedToWrite;
//设置成百分比形式
NSString *percent = [NSString stringWithFormat:@"下载进度 %0.0f%%", (double)totalBytesWritten/totalBytesExpectedToWrite*100];
self.progressLabel.text = percent;
}
其中一些点要注意下:
一、
UIProgressView的progress为float型,所以设置时也要为float型,否则不显示动画效果
self.progressView.progress = (float)totalBytesWritten/totalBytesExpectedToWrite;
效果而下:
没有强制转换
self.progressView.progress = totalBytesWritten/totalBytesExpectedToWrite;
效果而下:
二、
NSSearchPathForDirectoriesInDomains可以用来获取app的私有文件路径,即沙盒中的文件夹列表,获取的为数组形式。
//获取Document文件夹
NSString *document = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
//获取Cache文件夹
NSString *caches = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject];
标签:
原文地址:http://www.cnblogs.com/Apologize/p/4812703.html