iOS 知识整理--网络

150 阅读5分钟

本文转载自:吕阿蒙

网络--通信过程

请求

请求头:包含了对客户端的环境描述、客户端请求信息等

Host 客户端想访问的服务器主机地址

User-Agent 客户端的类型,客户端的软件环境

Accept 客户端所能接收的数据类型

Accept-Language 客户端的语言环境

Accept-Encoding 客户端支持的数据压缩格式

请求体:客户端发给服务器的具体数据,比如文件数据(POST请求才会有)

响应

客户端向服务器发送请求,服务器应当做出响应,即返回数据给客户端

响应头:包含了对服务器的描述、对返回数据的描述

Server 服务器的类型

Content-Type 返回数据的类型

Content-Length 返回数据的长度

Date 响应的时间

响应体:服务器返回给客户端的具体数据,比如文件数据

更多资料

网络--JSON

NSJSONSerialization(序列化工具)

NSJSONSerialization常见方法

JSON数据->OC对象

/*
1.JSON的二进制数据
2.枚举值
3.错误信息
*/
/*  NSJSONReadingOptions
    NSJSONReadingMutableContainers = (1UL << 0),可变字典和数组
    NSJSONReadingMutableLeaves = (1UL << 1),  内部所以的字符串都是可变的,iOS7之后有问题 ,一般不用
    NSJSONReadingAllowFragments = (1UL << 2) 既不是字典也不是数组,则必须使用该枚举值
*/
 
+ (nullable id)JSONObjectWithData:(NSData *)data options:(NSJSONReadingOptions)opt error:(NSError **)error;

OC对象->JSON数据

/*
注意:并不是所有的OC对象都能转换为JSON
    最外层必须是NSArray or NSDictionary
    所有的元素必须是NSArray,NSNumber,NSArray,NSDictory,or NSNull
    字典中所有的key都必须是NSString类型的
    NSNumber不能无穷大
*/
 
/*
1.要转换的OC对象
2.排序选项
    NSJSONWritingPrettyPrinted 排版 美观,但会改变原来的顺序
    NSJSONWritingSortedKeys 原来dic是什么顺序,输出还是什么顺序,对于JSON有顺序要求的选择这个
*/
 
+ (nullable NSData *)dataWithJSONObject:(id)obj options:(NSJSONWritingOptions)opt error:(NSError **)error;

网络--NSURLSession

使用步骤

使用NSURLSession对象创建Task,然后执行Task 注意:请求在子线程调用

GET请求

- (void)get{
    //确定URL
    NSURL *url = [NSURL URLWithString:@"url"];
    //创建请求对象
    NSURLRequest *quest = [NSURLRequest requestWithURL:url];
    //创建会话对象
    NSURLSession *session = [NSURLSession sharedSession];
    //创建Task
    //方法一
    NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:quest completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {   
    }];
    //方法二
    //内部会自动将请求路径作为参数创建一个请求对象(GET)
    NSURLSessionDataTask *dataTask = [session dataTaskWithURL:url completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
    }];
    //执行Task
    [dataTask resume];
}

POST请求

- (void)post{
    //确定URL
    NSURL *url = [NSURL URLWithString:@"url"];
    //创建请求对象
    NSMutableURLRequest *quest = [NSMutableURLRequest requestWithURL:url];
    //设置请求方法为POST
    quest.HTTPMethod = @"POST";
    //设置请求体
    quest.HTTPBody = [@"user=sas&pwd=123" dataUsingEncoding:NSUTF8StringEncoding];
    //创建会话对象
    NSURLSession *session = [NSURLSession sharedSession];
    //创建Task
    NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:quest completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
        
    }];
    //执行Task
    [dataTask resume];
}

代理

- (void)delegateTask{
    NSURL *url = [NSURL URLWithString:@"url"];
    //创建请求对象
    NSURLRequest *quest = [NSURLRequest requestWithURL:url];
    /*
     1.配置信息 [NSURLSessionConfiguration defaultSessionConfiguration]
     2.代理
     3.设置代理方法在哪个线程中调用
     */
    NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:[NSOperationQueue mainQueue]];
    //创建Task
    NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:quest];
    //执行Task
    [dataTask resume];
}
#pragma mark - NSURLSessionDataDelegate
/**
 接收服务器的响应 他默认会取消该请求
 @param session 会话对象
 @param dataTask 请求任务
 @param response 响应头信息
 @param completionHandler 回调 传给系统
 */
- (void)URLSession:(NSURLSession *)session dataTask:(nonnull NSURLSessionDataTask *)dataTask didReceiveResponse:(nonnull NSURLResponse *)response completionHandler:(nonnull void (^)(NSURLSessionResponseDisposition))completionHandler{
    /*NSURLSessionResponseCancel = 0,取消 默认
    NSURLSessionResponseAllow = 1, 接收
    NSURLSessionResponseBecomeDownload = 2, 变成下载任务
    NSURLSessionResponseBecomeStream 变成下载任务
    */
    completionHandler(NSURLSessionResponseAllow);
}
/**
 接收到服务器返回的数据 调用多次
 @param session 会话对象
 @param dataTask 请求任务
 @param data 本次下载的数据
 */
- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data{
    [self.fileData appendData:data];
}
/**
 请求结束或者是失败的时候调用
 @param session 会话对象
 @param task 请求任务
 @param error 错误信息
 */
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error{
    //解析数据
    NSLog(@"%@",[[NSString alloc]initWithData:self.fileData encoding:kCFStringEncodingUTF8]);
}

NSURLSessionDownloadTask 大文件下载

- (void)download{
    NSURL *url = [NSURL URLWithString:@"url"];
    //创建请求对象
    NSURLRequest *quest = [NSURLRequest requestWithURL:url];
    //创建session
    NSURLSession *session = [NSURLSession sharedSession];
    /**
     创建task
     @param location 下载路径
     @param response 响应头信息
     @param error 错误信息
     */
    //该方法内部已经实现了边接收数据边写沙盒(tmp)的操作 
    //由于是临时文件夹,所以不会长久保存
    //缺点:无法监听下载进度
    //优点:不用担心内存
    NSURLSessionDownloadTask *downloadTask = [session downloadTaskWithRequest:quest completionHandler:^(NSURL * _Nullable location, NSURLResponse * _Nullable response, NSError * _Nullable error) {
        //拼接文件全路径
        NSString *fullPath = [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject]stringByAppendingPathComponent:response.suggestedFilename];
        //剪切文件
        [[NSFileManager defaultManager]moveItemAtURL:location toURL:[NSURL URLWithString:fullPath] error:nil];
        
    }];
    [downloadTask resume];
}

离线断点下载

@property (nonatomic, strong) NSURLSessionDataTask *task;
@property (nonatomic, assign) NSInteger currentSize;
@property (nonatomic, assign) NSInteger totalSize;
@property (nonatomic, strong) NSString *fullPath;
@property (nonatomic, strong) NSFileHandle *handle;//文件句柄
@property (nonatomic, strong) NSURLSession *session;
- (NSURLSession *)session{
    if (_session == nil) {
        _session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:[NSOperationQueue mainQueue]];
    }
    return _session;
}
 
-(NSString *)fullPath{
    if (_fullPath == nil) {
        _fullPath = [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject]stringByAppendingPathComponent:@"111.mp4"];
    }
    return _fullPath;
}
 
- (NSURLSessionDataTask *)task{
    if (_task == nil) {
        NSURL *url = [NSURL URLWithString:@"url"];
        //创建请求对象
        NSMutableURLRequest *quest = [NSMutableURLRequest requestWithURL:url];
        //获取指定文件s路径对应文件的数据大小
        self.currentSize = [self getFileSize];
        //设置请求头,告诉服务器请求哪一部分数据
        NSString *range = [NSString stringWithFormat:@"bytes=%zd-",self.currentSize];
        [quest setValue:range forHTTPHeaderField:@"Range"];
        
        //创建Task
        _task= [self.session dataTaskWithRequest:quest];
    }
    return _task;
}
 
- (NSInteger)getFileSize{
    NSDictionary * info = [[NSFileManager defaultManager]attributesOfItemAtPath:self.fullPath error:nil];
    NSInteger currentSize = [info[@"NSFileSize"] integerValue];
    return currentSize;
}
 
#pragma mark - NSURLSessionDataDelegate
 
- (void)URLSession:(NSURLSession *)session dataTask:(nonnull NSURLSessionDataTask *)dataTask didReceiveResponse:(nonnull NSURLResponse *)response completionHandler:(nonnull void (^)(NSURLSessionResponseDisposition))completionHandler{
    
    self.totalSize = response.expectedContentLength+self.currentSize;
    if (self.currentSize == 0) {
        //创建空文件
        [[NSFileManager defaultManager]createFileAtPath:self.fullPath contents:nil attributes:nil];
        
    }
    //创建文件句柄
    self.handle = [NSFileHandle fileHandleForWritingAtPath:self.fullPath];
    //移动指针
    [self.handle seekToEndOfFile];
    
    completionHandler(NSURLSessionResponseAllow);
}
 
- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data{
    
    //写入数据到文件
    [self.handle writeData:data];
    self.currentSize += data.length;
}
 
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error{
    //解析数据
    [self.handle closeFile];
    self.handle = nil;
}
- (void)dealloc{
    //清理工作
    //[self.session finishTasksAndInvalidate]
    [self.session invalidateAndCancel];
}

文件上传

- (void)upload{
    NSURL *url = [NSURL URLWithString:@"aa"];
    
    //创建请求对象
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
    //设置请求方法
    request.HTTPMethod = @"POST";
    //设置请求头信息
    NSString *boundary = @"----WebKitFormBoundary8vNspBm1CiPXHhA5";//分隔符
    [request setValue:[NSString stringWithFormat:@"multipart/form-data;boundary=%@",boundary] forHTTPHeaderField:@"Content-Type"];
    //创建会话对象
    NSURLSession *session  = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:[NSOperationQueue mainQueue] ];
    //创建上传task
    /*
     1.请求对象
     2.传递要上传的数据
     3.
     
     */
    NSURLSessionUploadTask *task = [session uploadTaskWithRequest:request fromData:[self getBodyData] completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
        
    }];
    [task resume];
    
}
 
- (NSData *)getBodyData{
    return [NSData data];
}
 
///
/// @param session session
/// @param task task
/// @param bytesSent 本次发送的数据
/// @param totalBytesSent 上传完成的数据大小
/// @param 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/totalBytesSent);
}