美文网首页
iOS网络编程(NSURLSession)

iOS网络编程(NSURLSession)

作者: 夜雨聲煩_ | 来源:发表于2018-04-16 21:53 被阅读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有三个类构造函数:

    • defaultSessionConfiguration 返回标准默认配置,一般我们都使用这个
    • ephemeralSessionConfiguration 返回一个预设配置,没有持久性存储的缓存,Cookie或证书。可以用来实现像"无痕浏览"
    • backgroundSessionConfiguration 独特之处在于,它会创建一个后台会话。它甚至可以在应用程序挂起,退出,崩溃的情况下运行上传和下载任务

    其他配置:

    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:^{
             // 释放时做的操作
        }];
    }
    

    相关文章

      网友评论

          本文标题:iOS网络编程(NSURLSession)

          本文链接:https://www.haomeiwen.com/subject/zlzjkftx.html