iOS网络编程(NSURLSession)

2018-04-16  本文已影响0人  夜雨聲煩_

原文地址:https://www.jianshu.com/p/78964aac72d5

1. NSURLSesscion使用步骤

  1. 使用NSURLSession对象创建Task
  2. 执行Task
Task的类型
task类型.png

2.NSURLSesscion 常用方法

获得Session
获得共享的Session
+ (NSURLSession *)sharedSession;

自定义Session
+ (NSURLSession *)sessionWithConfiguration:(NSURLSessionConfiguration *)configuration delegate:(id <NSURLSessionDelegate>)delegate delegateQueue:(NSOperationQueue *)queue;
Session常用方法
常见方法
- (void)suspend; // 暂停
- (void)resume; // 恢复
- (void)cancel; // 取消
@property (readonly, copy) NSError *error; // 错误
@property (readonly, copy) NSURLResponse *response; // 响应

// 取消任务 这个方法可以拿到恢复下载需要的数据
- (void)cancelByProducingResumeData:(void (^)(NSData *resumeData))completionHandler;

3. NSURLSesscion 简单使用

1. GET请求
- (void)sessionGetMethod
{
    //获取session单例
    NSURLSession *session = [NSURLSession sharedSession];
    //创建url
    NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/login"];
    //根据url创建request请求
    NSURLRequest *request = [NSURLRequest requestWithURL:url];
    
    //以block形式根据request请求为参数创建任务 返回参数-data:响应体 response:响应头 error:错误信息
    NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
        NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil];
        NSLog(@"%@---%@",[dict descriptionWithLocale:nil], [NSThread currentThread]);

    }];
    //开始任务
    [dataTask resume];
    
}

运行结果如下:

2018-05-08 10:14:00.392311+0800 NSURLSesscion[3394:418080] {
    error = "用户名不存在";
}---<NSThread: 0x600000274b80>{number = 4, name = (null)}
2. POST请求
- (void)sessionPostMethod
{
    //获取session单例
    NSURLSession *session = [NSURLSession sharedSession];
    //创建url
    NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/login"];
    //根据url创建可变request请求
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
    //指定请求方式为post
    request.HTTPMethod = @"POST";
    //指定请求体
    request.HTTPBody = [@"username=520it&pwd=520it&type=JSON" dataUsingEncoding:NSUTF8StringEncoding];
    
    //以block形式根据request请求为参数创建任务 返回参数-data:响应体 response:响应头 error:错误信息
    NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
        NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil];
        NSLog(@"%@---%@",[dict descriptionWithLocale:nil], [NSThread currentThread]);
    }];
    //开始任务
    [dataTask resume];
}

运行结果如下:

2018-05-08 10:08:08.601784+0800 NSURLSesscion[3291:407316] {
    success = "登录成功";
}---<NSThread: 0x604000265fc0>{number = 4, name = (null)}

注意:通过打印可以看出回调方法在子线程中调用,如果在回调方法中拿到数据刷新UI,必须要回到主线程刷新UI。

3.代理方法请求 <NSURLSessionDataDelegate>
- (void)startButtonTouchesBegan:(id)event
{
    //创建session
    NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:[NSOperationQueue mainQueue]];
    //创建url
    NSURL *url =[NSURL URLWithString:@"http://120.25.226.186:32812/login?username=520it&pwd=520it&type=JSON"];
    //创建reqauest请求
    NSURLRequest *request = [NSURLRequest requestWithURL:url];
    //创建任务
    NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:request];
    //开始任务
    [dataTask resume];
}

#pragma mark - NSURLSessionDataDelegate代理方法
// 接收到服务器响应的时候调用
- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveResponse:(nonnull NSURLResponse *)response completionHandler:(nonnull void (^)(NSURLSessionResponseDisposition))completionHandler
{
    NSLog(@"didReceiveResponse 接受到服务器响应");
    // completionHandler 控制是否接受服务器返回的数据
    /**
     typedef NS_ENUM(NSInteger, NSURLSessionResponseDisposition) {
     NSURLSessionResponseCancel = 0, // 默认,表示取消接受数据,和[task cancel]相同
     NSURLSessionResponseAllow = 1,   // 接受数据
     NSURLSessionResponseBecomeDownload = 2, //Turn this request into a download
     NSURLSessionResponseBecomeStream NS_ENUM_AVAILABLE(10_11, 9_0) = 3, //Turn this task into a stream task
     }
     */
    completionHandler(NSURLSessionResponseAllow);
}

// 接收到服务器返回数据时调用,会调用多次
- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data
{
    NSLog(@"didReceiveData 接受到服务器返回数据");
}

// 当请求完成之后调用,如果请求失败error有值
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error
{
    NSLog(@"didCompleteWithError 请求完成");
}

运行结果如下:

2018-05-08 10:37:40.426230+0800 NSURLSesscion[3760:455576] didReceiveResponse 接受到服务器响应
2018-05-08 10:37:40.426556+0800 NSURLSesscion[3760:455576] didReceiveData 接受到服务器返回数据
2018-05-08 10:37:40.426888+0800 NSURLSesscion[3760:455576] didCompleteWithError 请求完成
4.NSURLSessionConfiguration 配置简单说明

NSURLSessionConfiguration 对象用于初始化 NSURLSession 对象。当 NSURLSession 开启多个任务 Task 的时候可以用 NSURLSessionConfiguration 对象统一配置。
NSURLSessionConfiguration有三个类构造函数:

其他配置:

NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
// 请求超时时间
configuration.timeoutIntervalForRequest = 10;
// 加载资源超时时间
configuration.timeoutIntervalForResource = 10;
// 蜂窝网络状态下是否可用
configuration.allowsCellularAccess = YES;

3. NSURLSesscion 文件下载

1. NSURLSessionDownloadTask实现断点下载

NSURLSession 提供了专用用来下载的 Task ,NSURLSessionDownloadTask,使用NSURLSessionDownloadTask 的代理方法或者本身提供的方法可以很轻松的实现断点下载。

- (void)downloadButtonTouchesBegan:(id)event
{
    [self sessionDownloadMethod];
}

- (void)sessionDownloadMethod
{
    NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:[NSOperationQueue mainQueue]];
    NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/resources/videos/minion_03.mp4"];
    self.downloadTask = [session downloadTaskWithURL:url];
    [self.downloadTask resume];
    
}

- (void)cancelButtonTouchesBegan:(id)event
{
    [self.downloadTask cancelByProducingResumeData:^(NSData * _Nullable resumeData) {
        
    }];
}
#pragma mark - NSURLSessionDownloadDelegate代理方法
// 1.当接收到数据的时候,写数据,该方法会调用多次
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite
{
    //bytesWritten:本次写入数据的大小
    //totalBytesWritten:已经下载完成的数据大小
    //totalBytesExpectedToWrite:文件大小
    //可以在这个方法中监听下载的进度 totalBytesWritten/totalBytesExpectedToWrite
    NSLog(@"本次写入数据大小:%lld --- 已经下载完成的数据大小:%lld --- :文件大小:%lld ",bytesWritten,totalBytesWritten,totalBytesExpectedToWrite);
    float number = 100.0 * totalBytesWritten / totalBytesExpectedToWrite;
    [self.downloadButton setTitle:[NSString stringWithFormat:@"%.1f %%",number] forState:UIControlStateNormal];
}

// 2.恢复下载的时候调用
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didResumeAtOffset:(int64_t)fileOffset expectedTotalBytes:(int64_t)expectedTotalBytes
{
    NSLog(@"didResumeAtOffset");
}

// 3.下载完成之后调用
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location
{
    // location :下载文件的存储位置,在沙盒tmp文件中。
    // tmp文件保存应用运行时所需的临时数据,使用完毕后会将相应的文件从该目录中删除,应用程序关闭时,系统会清除该目录下的文件
    // 程序下载完成之后我们可以将tmp中下载的文件移动到沙盒中保存。
    // NSLog(@"didFinishDownloading 下载完成,路径为:%@",location);
    
    NSFileManager *manager = [NSFileManager defaultManager];
    NSData *data =  [manager contentsAtPath:location.path];
    //保存下载的文件到沙盒
    NSString *caches = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject];
    //拼接文件全路径
    NSString *fullPath = [caches stringByAppendingPathComponent:@"abc.mp4"];
    //写入数据到文件
    [data writeToFile:fullPath atomically:YES];

}

通过以上方法可以很轻松的实现断点下载,但是使用 NSURLSessionDownloadTask 实现还有一些缺点,我们只有在下载完成之后才能拿到下载完成的文件,那么当我们下载到一半的时候,我们点击暂停,或者在下载过程中,直接关闭退出程序,此时因为文件是保存在内存中的,所以之前下载的文件已经不存在了,当我们重新运行程序,就需要重新下载。这种不可操纵性显然不是我们想要的。因此我们还是要使用 NSURLSessiondataTask 来实现离线断点下载。

2. NSURLSessiondataTask实现文件离线断点下载

原理:首先利用输出流实现边下载边存储数据到沙盒,另外在第一次接收到响应的时候将下载文件的大小也存储在沙盒中。然后当退出程序重新运行的时候,查看沙盒中是否有已经下载的文件,如果有就获取已经下载文件的大小,并取出沙盒中存储的文件总大小,将下载进度显示在界面,然后接着拼接下载。如果没有,则从0开始下载。

#import "DownloadViewController.h"

#define FileName @"chip.mp4"
#define FileLength @"chip.xx"

@interface DownloadViewController ()<NSURLSessionDataDelegate>

@property (strong, nonatomic) NSOutputStream *stream; //输出流
@property (assign, nonatomic) NSInteger totalLength; //总大小
@property (assign, nonatomic) NSInteger currentLength; //已经下载大小
@property (nonatomic, strong) NSURLSession *session;
@property (nonatomic, strong) NSURLSessionDataTask *dataTask;

@property (strong, nonatomic) UIProgressView *progressView;
@property (strong, nonatomic) UIButton *playBtn;
@property (strong, nonatomic) UIButton *startBtn;
@property (strong, nonatomic) UIButton *pauseBtn;
@property (strong, nonatomic) UIButton *deleteBtn;

@end

@implementation DownloadViewController

- (NSURLSessionDataTask *)dataTask
{
    if (!_dataTask) {
        self.currentLength = [self getCurrentLength];
        NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/resources/videos/minion_02.mp4"];
        NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
        NSString *range = [NSString stringWithFormat:@"bytes=%zd-",self.currentLength];
        [request setValue:range forHTTPHeaderField:@"Range"];
        _dataTask = [self.session dataTaskWithRequest:request];
    }
    return _dataTask;
}

- (NSURLSession *)session{
    if (!_session) {
        _session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:[NSOperationQueue mainQueue]];
    }
    return _session;
}

- (UIProgressView *)progressView
{
    if (!_progressView) {
        _progressView = ({
            UIProgressView *progressView = [[UIProgressView alloc] init];
            progressView.frame = CGRectMake(50, 100, 200, 50);
            progressView.tintColor = [UIColor redColor];
            progressView;
        });
    }
    return _progressView;
}

- (UIButton *)playBtn
{
    if (!_playBtn) {
        _playBtn = ({
            UIButton *button = [[UIButton alloc] init];
            button.frame = CGRectMake(200, 400, 100, 50);
            button.backgroundColor = [UIColor redColor];
            [button setTitle:@"播放" forState:UIControlStateNormal];
            [button setTitleColor:[UIColor lightGrayColor] forState:UIControlStateDisabled];
            [button setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
            [button addTarget:self action:@selector(playBtnEvent:) forControlEvents:UIControlEventTouchUpInside];
            button.enabled = NO;
            button;
        });
    }
    return _playBtn;
}

- (UIButton *)pauseBtn
{
    if (!_pauseBtn) {
        _pauseBtn = ({
            UIButton *button = [[UIButton alloc] init];
            button.frame = CGRectMake(200, 300, 100, 50);
            button.backgroundColor = [UIColor redColor];
            [button setTitle:@"暂停" forState:UIControlStateNormal];
            [button addTarget:self action:@selector(pauseBtnEvent:) forControlEvents:UIControlEventTouchUpInside];
            button;
        });
    }
    return _pauseBtn;
}

- (UIButton *)startBtn
{
    if (!_startBtn) {
        _startBtn = ({
            UIButton *button = [[UIButton alloc] init];
            button.frame = CGRectMake(200, 200, 100, 50);
            button.backgroundColor = [UIColor redColor];
            [button setTitle:@"开始/继续" forState:UIControlStateNormal];
            [button addTarget:self action:@selector(startBtnEvent:) forControlEvents:UIControlEventTouchUpInside];
            button;
        });
    }
    return _startBtn;
}

- (UIButton *)deleteBtn
{
    if (!_deleteBtn) {
        _deleteBtn = ({
            UIButton *button = [[UIButton alloc] init];
            button.frame = CGRectMake(200, 500, 100, 50);
            button.backgroundColor = [UIColor redColor];
            [button setTitle:@"删除" forState:UIControlStateNormal];
            [button addTarget:self action:@selector(deleteBtnEvent:) forControlEvents:UIControlEventTouchUpInside];
            button;
        });
    }
    return _deleteBtn;
}

- (void)viewDidLoad {
    [super viewDidLoad];
    self.view.backgroundColor = [UIColor whiteColor];
    [self.view addSubview:self.progressView];
    [self.view addSubview:self.startBtn];
    [self.view addSubview:self.pauseBtn];
    [self.view addSubview:self.playBtn];
    [self.view addSubview:self.deleteBtn];

    NSString *caches = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject];
    NSString *filePath = [caches stringByAppendingPathComponent:FileName];
    NSMutableDictionary *dict = [NSMutableDictionary dictionaryWithContentsOfFile:filePath];
    if (dict) {
        self.progressView.progress = 1.0 * [self getCurrentLength] / [dict[filePath] integerValue];
        if (self.progressView.progress == 1) {
            self.playBtn.enabled = YES;
        }
    }
    // Do any additional setup after loading the view.
}

- (NSInteger)getCurrentLength
{
    NSString *caches = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject];
    NSString *filePath = [caches stringByAppendingPathComponent:FileName];
    NSFileManager *manager = [NSFileManager defaultManager];
    NSDictionary *dict = [manager attributesOfItemAtPath:filePath error:nil];
    return [dict[@"NSFileSize"] integerValue];
}

- (void)saveTotal:(NSInteger)length
{
    NSLog(@"开始储存文件大小");
    NSString *caches = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject];
    NSString *filePath = [caches stringByAppendingPathComponent:FileLength];
    NSMutableDictionary *dict = [NSMutableDictionary dictionary];
    [dict setObject:@(length) forKey:FileLength];
    [dict writeToFile:filePath atomically:YES];
}

- (void)startBtnEvent:(id)event
{
    [self.dataTask resume];
}

- (void)pauseBtnEvent:(id)event
{
    [self.dataTask suspend];
}

- (void)playBtnEvent:(id)event
{
    UIAlertController *action = [UIAlertController alertControllerWithTitle:@"播放" message:@"可以播放" preferredStyle:UIAlertControllerStyleAlert];
    [self presentViewController:action animated:YES completion:nil];
}

- (void)deleteBtnEvent:(id)event
{
    NSString *caches = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject];
    NSString *filePath = [caches stringByAppendingPathComponent:FileName];
    NSFileManager *manager = [NSFileManager defaultManager];
    [manager removeItemAtPath:filePath error:nil];
    self.currentLength = 0;
    NSLog(@"删除成功");
    self.progressView.progress = 0;
}

#pragma mark - NSURLSessionDataDelegate 代理方法
- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveResponse:(NSURLResponse *)response completionHandler:(void (^)(NSURLSessionResponseDisposition))completionHandler
{
    // 拿到文件总大小 获得的是当次请求的数据大小,当我们关闭程序以后重新运行,开下载请求的数据是不同的 ,所以要加上之前已经下载过的内容
    NSLog(@"接收到服务器响应");
    self.totalLength = response.expectedContentLength + self.currentLength;
    // 把文件总大小保存的沙盒 没有必要每次都存储一次,只有当第一次接收到响应,self.currentLength为零时,存储文件总大小就可以了
    if (self.currentLength == 0) {
        [self saveTotal:self.totalLength];
    }
    
    NSString *caches = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject];
    NSString *filePath = [caches stringByAppendingPathComponent:FileName];
    NSLog(@"%@",filePath);
    
    NSOutputStream *stream = [[NSOutputStream alloc] initToFileAtPath:filePath append:YES];
    [stream open];
    self.stream = stream;
    
    completionHandler(NSURLSessionResponseAllow);
}

- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data
{
    self.currentLength += data.length;
    //输出流写数据
    [self.stream write:data.bytes maxLength:data.length];
    NSLog(@"%f",1.0 * self.currentLength / self.totalLength);
    self.progressView.progress = 1.0 * self.currentLength / self.totalLength;
}

- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error
{
    [self.stream close];
    self.stream = nil;
    NSLog(@"didCompleteWithError 请求完成");
    self.playBtn.enabled = YES;
}


- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

/*
#pragma mark - Navigation

// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
    // Get the new view controller using [segue destinationViewController].
    // Pass the selected object to the new view controller.
}
*/

@end

4. NSURLSessiond上传文件

1. NSURLSessionUploadTask上传文件
- (void)uploadButtonEvent:(id)event
{
    NSURLSession *session = [NSURLSession sharedSession];
    NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/upload"];
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
    request.HTTPMethod = @"POST";
    NSString *header = [NSString stringWithFormat:@"multipart/form-data; boundary=%@",Kboundary];
    [request setValue:header forHTTPHeaderField:@"Content-Type"];

     // session上传不需要设置请求体,如果数据在request中会被忽略。
    NSURLSessionUploadTask *uploadTask = [session uploadTaskWithRequest:request fromData:[self getBody] completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
        NSLog(@"%@",[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]);
    }];
    [uploadTask resume];
}

- (NSData *)getBody
{

    NSMutableData *fileData = [NSMutableData data];
    //文件参数格式
    /*
     --分隔符
     Content-Disposition: form-data; name="file"; filename="123.png"
     Content-Type: image/png
     空行
     文件数据
     */
    NSString *str = [NSString stringWithFormat:@"--%@",Kboundary];
    //--分隔符
    [fileData appendData:[str dataUsingEncoding:NSUTF8StringEncoding]];
    //换行
    [fileData appendData:KNewLine];
    //Content-Disposition: form-data; name="file"; filename="123.png"
    [fileData appendData:[@"Content-Disposition: form-data; name=\"file\"; filename=\"123.png\"" dataUsingEncoding:NSUTF8StringEncoding]];
    //换行
    [fileData appendData:KNewLine];
    //Content-Type: image/png
    [fileData appendData:[@"Content-Type: image/png" dataUsingEncoding:NSUTF8StringEncoding]];
    //换行
    [fileData appendData:KNewLine];
    //空行
    [fileData appendData:KNewLine];
    //换行
    [fileData appendData:KNewLine];
    //文件数据
    UIImage *image = [UIImage imageNamed:@"123"];
    NSData *imageData = UIImagePNGRepresentation(image);
    [fileData appendData:imageData];
    //换行
    [fileData appendData:KNewLine];

    //5.2 非文件参数
    /*
     --分隔符
     Content-Disposition: form-data; name="username"
     空行
     yy
     */
    [fileData appendData:[str dataUsingEncoding:NSUTF8StringEncoding]];
    [fileData appendData:KNewLine];
    [fileData appendData:[@"Content-Disposition: form-data; name=\"username\"" dataUsingEncoding:NSUTF8StringEncoding]];
    [fileData appendData:KNewLine];
    [fileData appendData:KNewLine];
    [fileData appendData:KNewLine];
    [fileData appendData:[@"yy" dataUsingEncoding:NSUTF8StringEncoding]];
    [fileData appendData:KNewLine];

    //5.3 结尾标识
    /*
     --分隔符--
     */
    [fileData appendData:[[NSString stringWithFormat:@"--%@--",Kboundary] dataUsingEncoding:NSUTF8StringEncoding]];
    [fileData appendData:KNewLine];

    return fileData;
}

运行结果如下:

2018-05-09 14:58:38.101663+0800 NSURLSesscion[11074:1637141] {"success":"上传成功"}
2. NSURLSessionUploadTask 代理方法上传
NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:[NSOperationQueue mainQueue]];

#pragma mark NSURLSessionDataDelegate 代理方法
/*
 bytesSent:本次上传数据大小
 totalBytesSent:总共上传了多少
 totalBytesExpectedToSend:文件大小
 */
-(void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didSendBodyData:(int64_t)bytesSent totalBytesSent:(int64_t)totalBytesSent totalBytesExpectedToSend:(int64_t)totalBytesExpectedToSend
{
    NSLog(@"%f",1.0 *totalBytesSent /totalBytesExpectedToSend);
}
// 上传结束
-(void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error
{
    NSLog(@"上传结束");
}
@end

5. NSURLSession 内存释放问题

NSURLSession 需要释放,不然会引起内存泄漏

-(void)dealloc
{
    //注意:在不用的时候一定要调用该方法来释放,不然会出现内存泄露问题
    //方法一:取消所有过去的会话和任务
    [self.session invalidateAndCancel];
    //方法二:可在释放时做一些操作
    [self.session resetWithCompletionHandler:^{
         // 释放时做的操作
    }];
}
上一篇下一篇

猜你喜欢

热点阅读