iOS-原生网络请求(详细说明)

技 术 文 章 / 超 人


GET,POST基本带参数网络请求

   //请求地址
    NSURL *url = [NSURL URLWithString:URLString];
    
    //设置请求地址
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
    
    //设置请求方式
    request.HTTPMethod = @"POST";
    
    //设置请求参数
    request.HTTPBody = [parameters dataUsingEncoding:NSUTF8StringEncoding];
  //关于parameters是NSDictionary拼接后的NSString.关于拼接看后面拼接方法说明
    
    
    //设置请求session
    NSURLSession *session = [NSURLSession sharedSession];
    
    //设置网络请求的返回接收器
    NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
        dispatch_async(dispatch_get_main_queue(), ^{
            if (error) {
                if (failure) {
                    failure(error);
                }
            }else
            {
                NSError *error;
                NSMutableDictionary *responseObject = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:&error];
                if (error) {
                    if (failure) {
                        failure(error);
                    }
                }else
                {
                    if (success) {
                        success(responseObject);
                    }
                }
            } 
        });
    }];
//开始请求
    [dataTask resume];

拼接parameters 参数

/**
 拼接字典数据

 @param parameters 参数
 @return 拼接后的字符串
 */
-(NSString *)parameters:(NSDictionary *)parameters
{
    //创建可变字符串来承载拼接后的参数
    NSMutableString *parameterString = [NSMutableString new];
    //获取parameters中所有的key
    NSArray *parameterArray = parameters.allKeys;
    for (int i = 0;i < parameterArray.count;i++) {
    //根据key取出所有的value
        id value = parameters[parameterArray[i]];
    //把parameters的key 和 value进行拼接
        NSString *keyValue = [NSString stringWithFormat:@"%@=%@",parameterArray[i],value];
        if (i == parameterArray.count || i == 0) {
        //如果当前参数是最后或者第一个参数就直接拼接到字符串后面,因为第一个参数和最后一个参数不需要加 “&”符号来标识拼接的参数
            [parameterString appendString:keyValue];
        }else
        {
        //拼接参数, &表示与前面的参数拼接
            [parameterString appendString:[NSString stringWithFormat:@"&%@",keyValue]];
        }
    }
    return parameterString;
}

上传文件原生请求

NSURLRequestCachePolicy 缓存枚举说明

//指定缓存逻辑。URL加载系统提供了一个磁盘和内存混合的缓存,来相应网络请求。这个缓存允许一个应用减少对网络连接的依赖,并且增加性能。使用缓存的目的是为了使用的应用程序能更快速的响应用户输入,是程序高效的运行。有时候我们需要将远程web服务器获取的数据缓存起来,减少对同一个url多次请求。
typedef NS_ENUM(NSUInteger, NSURLRequestCachePolicy)
{
    NSURLRequestUseProtocolCachePolicy = 0,//默认缓存策略。具体工作:如果一个NSCachedURLResponse对于请求并不存在,数据将会从源端获取。如果请求拥有一个缓存的响应,那么URL加载系统会检查这个响应来决定,如果它指定内容必须重新生效的话。假如内容必须重新生效,将建立一个连向源端的连接来查看内容是否发生变化。假如内容没有变化,那么响应就从本地缓存返回数据。如果内容变化了,那么数据将从源端获取

    NSURLRequestReloadIgnoringLocalCacheData = 1,// URL应该加载源端数据,不使用本地缓存数据

    NSURLRequestReloadIgnoringLocalAndRemoteCacheData = 4, // 本地缓存数据、代理和其他中介都要忽视他们的缓存,直接加载源数据

    NSURLRequestReloadIgnoringCacheData = NSURLRequestReloadIgnoringLocalCacheData,//两个的设置相同

    NSURLRequestReturnCacheDataElseLoad = 2,//使用缓存数据,忽略其过期时间;只有在没有缓存版本的时候才从源端加载数据。
    NSURLRequestReturnCacheDataDontLoad = 3,//只使用cache数据,如果不存在cache,请求失败;用于没有建立网络连接离线模式

    NSURLRequestReloadRevalidatingCacheData = 5, //指定如果已存的缓存数据被提供它的源段确认为有效则允许使用缓存数据响应请求,否则从源段加载数据。
};
//只有响应http和https的请求会被缓存。ftp和文件协议当被缓存策略允许的时候尝试接入源段。自定义的NSURLProtocol类能够保护缓存,如果它们被选择使用的话。

mimeType 文件类型

image.png

上传文件请求

//指定NSMutableURLRequest的 url请求地址、缓存机制、超时时长
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:URLString]
                                                           cachePolicy:NSURLRequestReloadIgnoringLocalCacheData
                                                       timeoutInterval: self.timeoutInterval];

    //指定加载进度的回调
    self.progressBlock = upProgress;
    
    /*
      multipart/from-data 编码类型,以提高二进制文件的传输效率。是一种进行表单提交时的消息格式。表单提交数据的时候,默认类型是application/x-www-form-urlencoded,也就是key=value的键值对格式,提交文件的时候使用multipart/from-data。因为是表单提交,所以http请求方式是POST。然后在请求头里设置Content-Type为multipart/from-data指定请求的格式
      charset=utf-8 编码格式
      boundary 分隔符,分隔多个文件、表单项。确保整个分隔符不会在文件或表单项的内容中出现。
    */
    //设置HTTPHeader中Content-Type的值
    [request setValue:[[NSString alloc] initWithFormat:@"multipart/form-data; charset=utf-8; boundary=%@",self.boundary] forHTTPHeaderField:@"Content-Type"];

    //请求方式
    request.HTTPMethod = @"POST";
    
    /*
     parameters 请求参数
     fileData 上传的文件 NSData类型
     name 文件名,一般随意取或与服务器协商
     fileName 文件加后缀名,例如传图片  就取  test.jpg 一般随意取或与服务器协商
      mimeType 文件类型
    */
   //该方法拼接上传文件的 Data数据
    NSData * payloadData = [self setBodydataWithParameters:parameters fileData:fileData name:name fileName:fileName mimeType:mimeType];

    /* 1、defaultSessionConfiguration"返回标准配置,这实际上与NSURLConnection的网络协议栈是一样的,具有相同的共享NSHTTPCookieStorage,共享NSURLCache和共享NSURLCredentialStorage。
  2、 "ephemeralSessionConfiguration"返回一个预设配置,没有持久性存储的缓存,Cookie或证书。这对于实现像"秘密浏览"功能的功能来说,是很理想的。
  3、 "backgroundSessionConfiguration":独特之处在于,它会创建一个后台会话。后台会话不同于常规的,普通的会话,它甚至可以在应用程序挂起,退出,崩溃的情况下运行上传和下载任务。初始化时指定的标识符,被用于向任何可能在进程外恢复后台传输的守护进程提供上下文。
    * /
    //NSURLSessionConfiguration对象用于初始化NSURLSession对象
    NSURLSessionConfiguration *sessionConfig = [NSURLSessionConfiguration defaultSessionConfiguration];

    //如果要使用代理方法,需要设置代理,但从NSURLSession的头文件发现session的delegate属性是只读的.因此设置代理要通过session的初始化方法赋,delegateQueue参数表示协议方法将会在哪个队列(NSOperationQueue)里面执行.
    NSURLSession *session = [NSURLSession sessionWithConfiguration:sessionConfig delegate:self delegateQueue:nil];
    
    
    
    NSURLSessionUploadTask * uploadtask = [session uploadTaskWithRequest:request fromData:payloadData completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
        dispatch_async(dispatch_get_main_queue(), ^{
            if (!error) {
                NSError *jserror = nil;
                NSDictionary *dic = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:&jserror];
                if (jserror) {
                    if (failure){
                        failure(jserror);
                    }
                }else if (success) {
                    success(dic);
                }
            }else if (failure){
                failure(error);
            }
        });
        
    }];
    //开始请求
    [uploadtask resume];

上传文件Data拼接方法

/**
 文件Data拼接

 @param parameter 上传参数
 @param data 文件源
 @param name 文件名
 @param fileName 文件加后缀的具体名称
 @param mimeType 文件类型
 @return 拼接后的Data
 */
- (NSData *)setBodydataWithParameters:(NSDictionary *)parameter
                             fileData:(NSData *)data
                                 name:(NSString *)name
                             fileName:(NSString *)fileName
                             mimeType:(NSString *)mimeType
{
    
    NSData * imageData = data;
    //1.构造body string
    NSMutableString *bodyString = [[NSMutableString alloc] init];
    
    //2.拼接body string
    NSMutableData *bodyData = [NSMutableData data];
    [parameter enumerateKeysAndObjectsUsingBlock:^(NSString *  _Nonnull key, NSString *  _Nonnull obj, BOOL * _Nonnull stop) {
        [bodyString appendFormat:@"--%@\r\n", self.boundary];
        [bodyString appendFormat:@"Content-Disposition: form-data; name=\"%@\"\r\n\r\n",key];
        [bodyString appendFormat:@"%@\r\n",obj];
    }];
    
    [bodyString appendFormat:@"--%@\r\n", self.boundary];
    [bodyString appendFormat:@"Content-Disposition: form-data; name=\"%@\"; filename=\"%@\"\r\n",name,fileName];
    [bodyString appendFormat:@"Content-Type: %@\r\n\r\n",mimeType];
    
    //拼接的过程
    //前面的bodyString, 其他参数
    [bodyData appendData:[bodyString dataUsingEncoding:NSUTF8StringEncoding]];
    //图片数据
    [bodyData appendData:imageData];
    
    //4.结束的分隔线
    NSString *endStr = [NSString stringWithFormat:@"\r\n--%@--\r\n",self.boundary];
    //拼接到bodyData最后面
    [bodyData appendData:[endStr dataUsingEncoding:NSUTF8StringEncoding]];
    
    return bodyData;
}

关于NSURLSessionDelegate

上传进度获取

/*
 调用该方法上传文件数据
 如果文件数据很大,那么该方法会被调用多次
 参数说明:
     totalBytesSent:已经上传的文件数据的大小
     totalBytesExpectedToSend:文件的总大小
 */
-(void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didSendBodyData:(int64_t)bytesSent totalBytesSent:(int64_t)totalBytesSent totalBytesExpectedToSend:(int64_t)totalBytesExpectedToSend{
    
    self.uploadProgress.totalUnitCount = totalBytesExpectedToSend;
    self.uploadProgress.completedUnitCount = totalBytesSent;
    //这里的progressBlock、uploadProgress都是自己定义的回调。上面上传文件中也有设置
    self.progressBlock(self.uploadProgress) ;
}

参考资料:
1.NSURLSession使用说明及后台工作流程分析
2.iOS开发之网络编程--6、NSURLSessionConfiguration笔记
3.使用NSURLSession

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,332评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,508评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,812评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,607评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,728评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,919评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,071评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,802评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,256评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,576评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,712评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,389评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,032评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,798评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,026评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,473评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,606评论 2 350

推荐阅读更多精彩内容

  • NSURLSession 使用步骤使用NSURLSession对象创建Task,然后执行Task -(void)g...
    BEYOND黄阅读 900评论 0 0
  • iOS开发系列--网络开发 概览 大部分应用程序都或多或少会牵扯到网络开发,例如说新浪微博、微信等,这些应用本身可...
    lichengjin阅读 3,648评论 2 7
  • 218.241.181.202 wxhl60 123456 192.168.10.253 wxhl66 wxhl6...
    CYC666阅读 1,369评论 0 6
  • 同步请求和异步请求- 同步请求:阻塞式请求,会导致用户体验的中断- 异步请求:非阻塞式请求,不中断用户体验,百度地...
    WangDavid阅读 583评论 0 0
  • 1.在开发的时候可以创建一个工具类,继承自我们的AFN中的请求管理者,再控制器中真正发请求的代码使用自己封装的工具...
    红楼那一场梦阅读 3,487评论 2 3