iOS网络学习之“远离NSURLConnection 走进NSURLSession”

  目前,在iOS的开发中,NURLConnection已经成为了过去式,现在的NSURLConnection已经deprected(iOS7之后),取而代之的是NSURLSession。而且AFNetworking 也已经换成了NSURLSession。既然是大势所趋,现总结NSURLSession用法如下:

  首先,是根据简单地按钮实现对应的网络操作:

 1.NSURLSessiion 的GET网络请求:

   要实现网络请求,首先,要准备好URLl 和 必要的参数,而GET最大的特点就是参数是直接的拼接在URL的后面,(路径?参数名=参数值)。然后,就可以通过NSURLSession和NSURLSessionTask愉快的进行GET网络请求了。注意,task要手动开启[task resume];。

具体使用代码如下:

- (IBAction)oneAction:(UIButton *)sender {

/**
     *  get请求
     *
     */
NSString * name=@"jredu";
NSString * psw=@"123";
NSURL * url=[NSURLURLWithString:[NSStringstringWithFormat:@"http://localhost/logo.php?userName=%@&pwd=%@",name,psw]];

//>初始化session
NSURLSession * session=[NSURLSessionsharedSession];

NSURLSessionTask * task=[session dataTaskWithURL:url completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
//将返回的二进制数据转为字符串
NSString * str=[[NSStringalloc] initWithData:data encoding:NSUTF8StringEncoding];

NSLog(@"%@",str);

    }];

//开始任务
    [task resume];

}

  2.使用NSURLSession进行POST网络请求:

    通过POST方式请求网络,同样是准备好URL,而与GET方式的不同之处:POST时,所需的参数并不是拼接在URL上的,POST的参数通过NSURLRequest传递(NSData);

准备好参数和URL之后任然是通过NSURLSession和NSURLSessionTask进行网络请求。同样注意:手动开启任务[task resume];

  具体的使用代码如下:

#pragma mark - post请求
- (IBAction)twoAction:(UIButton *)sender {

NSString *name=@"codeJerenal";
NSString *psw=@"123";

NSURL * url =[NSURLURLWithString:@"http://localhost/login_post.php"];

NSString * dataStr=[NSStringstringWithFormat:@"userName=%@&psw=%@",name,psw];
/** 字符串转data */
NSData * data=[dataStr dataUsingEncoding:NSUTF8StringEncoding];

/** 初始化可变的请求--设置数据 */
NSMutableURLRequest * request=[NSMutableURLRequestrequestWithURL:url];

    [request setHTTPMethod:@"POST"];
    [request setHTTPBody:data];

/** 初始化session */
NSURLSession * session=[NSURLSessionsharedSession];

NSURLSessionTask * task=[session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {

/** data转字符串调用类方法 */
NSString *retutnStr=[[NSStringalloc] initWithData:data encoding:NSUTF8StringEncoding];
NSLog(@"%@",retutnStr);
    }];

//>开始任务
    [task resume];
}

3,使用NSURLSession下载:

    要下载数据,首先,要给出要下载的资源的网络路径URL;

   NSURLSession 可以通过NSURLRequest初始化NSURLSession下载,也可以直接使用URL;

   下载成功之后的文件、数据会放在沙盒中的tmp文件中,作为一个临时的文件(返回的location就是其本地的URL),所以在下载成功之后的块中,要及时的将所下载的内容转移到Document中存放(通过NSFileManager)。在移动文件的过程中要注意location是本地的URL 所以,目的地路劲也是URL 应该使用[NSURL fileURLWithString:string];

   在下载完成之后,还会返回一个,NSURLResponse * response,可以通过其中的属性response.suggestedFileame作为文件在本地的命名;

     具体的使用如下所示:

#pragma mark - 下载数据
- (IBAction)sessionDownLoadAction:(UIButton *)sender {

//>URL路径
NSURL * url=[NSURLURLWithString:@"http://localhost/test.zip"];

//>初始化session
NSURLSession * session=[NSURLSessionsharedSession];

//>定义request
NSURLRequest * request=[NSURLRequestrequestWithURL:url cachePolicy:NSURLRequestUseProtocolCachePolicytimeoutInterval:20];

//>定义任务
NSURLSessionDownloadTask * downLoadTask=[session downloadTaskWithRequest:request completionHandler:^(NSURL * _Nullable location, NSURLResponse * _Nullable response, NSError * _Nullable error) {

//本地沙盒路径
NSString * path=[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject];

//文件下载后的存放路径-(转为本地URL使用)(字符串拼接方式,构造本地路径)
// NSString * fPath=[path stringByAppendingPathComponent:response.suggestedFilename];
/** 转换 */
// NSURL * desUrl=[NSURL fileURLWithPath:fPath];

/** 为本地路径准备path (格式化方式,构造本地路径)*/
NSString * filePath=[NSStringstringWithFormat:@"file://%@/%@",path,response.suggestedFilename];

/** 转为本地的URL */
NSURL * destinationUrl=[NSURLURLWithString:filePath];

//移动
NSFileManager * manager =[NSFileManagerdefaultManager];

NSError * error2;
BOOL isSuccess = [manager moveItemAtURL:location toURL:destinationUrl error:&error2];
if (isSuccess) {

NSLog(@"成功");

        }else{

NSLog(@"失败");
NSLog(@"%@",error2);
        }

    }];
[task resume];
}

4,NSURLSession实现下载的暂停和继续;

   ①:过程中要用到代理方法,而NSURLSession是在初始化的同时设置代理的,并且同时进行下载的设置

NSURLSessionConfiguration

参数一 session配置

参数二设置代理

参数三设置代理队列

NSURLSession * session = [NSURLSessionsessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:selfdelegateQueue:[NSOperationQueuemainQueue]];

  ②:通过按钮(或其他的方式)控制下载的暂停继续:

   核心:取消下载任务并保存已经下载的数据

[self.downTask cancelByProducingResumeData:^(NSData * _Nullable resumeData) {
self.resumeData=resumeData; }];
核心: 通过之前保存的已经下载的数据,继续下载
self.downTask =[self.session downloadTaskWithResumeData:self.resumeData];
[self.downTask resume];
 
#pragma mark - 控制起停按钮,点击事件
- (void) clickAction:(UIButton *)button{

    button.selected=!button.selected;
if (button.selected) {

   [self.downTask cancelByProducingResumeData:^(NSData * _Nullable resumeData) {
    /** 全局,用作断点下载存放已经下载的数据*/
    self.resumeData=resumeData;
       }];

    }else{

self.downTask =[self.session downloadTaskWithResumeData:self.resumeData];

/** 重新启动任务 */
        [self.downTask resume];
    }

}

③:下载过程中的主要代理方法

#pragma mark - 下载数据的代理方法

/**
 *  代理方法:每次数据下载成功调用方法
 *
 *  @param session                   代理的session
 *  @param downloadTask              代理的task
 *  @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{


NSLog(@"%lld===%lld=====%lld",bytesWritten,totalBytesWritten,totalBytesExpectedToWrite);

/** 主线程显示下载进度 */
dispatch_async(dispatch_get_main_queue(), ^{
if (totalBytesWritten==totalBytesExpectedToWrite) {

_curProgress.frame=CGRectMake(20, 500, 320, 30);
        }else{

_curProgress.frame=CGRectMake(20, 500, totalBytesWritten*(1.0)/totalBytesExpectedToWrite*(1.0)*320, 30);
/** 随机背景色 */
_curProgress.backgroundColor=[UIColorcolorWithRed:arc4random_uniform(255)/255.0green:arc4random_uniform(255)/255.0blue:arc4random_uniform(255)/255.0alpha:1];
        }


    });

}

 

/**
 *  代理方法:下载完成时调用--已经下载的文件从临时存放处移动到document中
 *
 *  @param session      代理的session
 *  @param downloadTask 代理的task
 *  @param location     下载文件的临时存放路径
 */
- (void) URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location{

NSString * documentPath=[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject];

NSString * filePath =[documentPath stringByAppendingPathComponent:downloadTask.response.suggestedFilename];

NSURL * loaclUrl =[NSURLfileURLWithPath:filePath];
NSLog(@"%@",loaclUrl);

//移动
NSError * err;
BOOL isSuccess=[[NSFileManagerdefaultManager] moveItemAtURL:location toURL:loaclUrl error:&err];
if (isSuccess) {
NSLog(@"下载成功");
    }else{

NSLog(@"失败");
NSLog(@"%@",err);
    }

}
#pragma mark *** 下载结束
- (void) URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error{

/**
如果是其他的原因导致下载失败,程序会走本方法,可以通过
      self.resumeData = error[NSURLSessionDownloadTaskResumeData];
找到已经下载的数据,解决失败原因之后,可以继续下载
     */

if (error) {
NSLog(
@"%@",error);
}
else { NSLog(@"成功"); } }

 

posted @ 2016-08-01 21:08  wangwei_Carry  阅读(290)  评论(0编辑  收藏  举报