博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
AFNetworking封装思路简析
阅读量:4443 次
发布时间:2019-06-07

本文共 6323 字,大约阅读时间需要 21 分钟。

 

一、AFNetworking的发展

1. AFN 1.0版本

AFN 的基础部分是 AFURLConnectionOperation,一个 NSOperation 子类,实现了 基于NSURLConnection 相关的delegate+blocks,网络部分是由 NSURLConnection 完成,然后利用 NSOperation 的 state(isReady→isExecuting→isFinished) 变化来进行网络控制。网络请求是在一个指定的线程(networkRequestThread)完成。 

AFURLConnectionOperation是一个很纯粹的网络请求 operation,可以对他进行 start/cancel/pause/resume 操作,可以获取对应的 NSURLRequest 和 NSURLResponse 数据。提供了 uploadPress 和downloadProgress 以方便其他使用。 
AFHTTPRequestOperation是 AFURLConnectionOperation 的子类,针对 HTTP+HTTPS 协议做了一层封装,比如statusCode、Content-Type 等,添加了请求成功和失败的回调 block,提供了addAcceptableContentTypes: 以方便上层使用。

2. AFN 2.0版本

NSURLSession 

NSURLSession 是  7 新引入的用于替代 NSURLConnection 的类。NSURLConnection 并没有被弃用,今后一段时间应该也不会(事实上最终还是被弃用了)。它们有一些重叠,AFNetworking提供了更高层次的抽象,并最大程度扩展了它的实用性。 
模块化 
对于AFNetworking的主要批评之一是笨重。虽然它的构架使在类的层面上是模块化的,但它的包装并不允许选择独立的一些功能。随着时间的推移,AFHTTPClient 尤其变得不堪重负。 在AFNetworking 2.0 中,你可以挑选并通过 CocoaPods subspecs 选择你所需要的组件

3. AFN 3.0版本

AFN 3.0+弃用NSURLConnection,只提供NSURLSession的支持。

二、NSURLSession简单实用

1. 普通的GET/POST请求

  1. 获取URL
  2. 创建request,修改请求方法、请求体(GET请求不需要)
  3. 获取全局Session
  4. 发起任务(进行反序列化)
  5. 结束任务

2. 上传请求

NSData *imageData = UIImagePNGRepresentation(image);    //1.NSURL    NSURL *url = [NSURL URLWithString:@"http://localhost/post/upload.php"];    //2.NSMutableURLRequest NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; //2.1 改请求方法 request.HTTPMethod = @"POST"; //2.2.设置请求头,boundary 这个就是一个分隔符,可以随便写, 只要不是中文 NSString *contentTypevalue = [NSString stringWithFormat:@"multipart/form-data; boundary=%@", kBoundaryUpload]; [request setValue:contentTypevalue forHTTPHeaderField:@"Content-Type"]; //NSURLSession不要把上传的文件放入请求体中,应该放在NSURLSession的方法中 NSData *fileData = [self formDataWithFileData:imageData serverFieldName:@"userfile" fileSaveName:@"abc.png"]; //3.获取系统提供的NSURLSession NSURLSession *globalSession = [NSURLSession sharedSession]; //4.由session发起上传任务 [[globalSession uploadTaskWithRequest:request fromData:fileData completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) { //4.反序列化 if (error==nil && data.length>0) { id result =[NSJSONSerialization JSONObjectWithData:data options:0 error:NULL]; NSLog(@"login-----%@",result); } }] resume];
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
- (NSData *)formDataWithFileData:(NSData *)fileData serverFieldName:(NSString *)serverFieldName fileSaveName:(NSString *)fileSaveName{    //1.NSMutableData    NSMutableData *dataM = [NSMutableData data];    /**     -----------------------------11454065798049615451989194362     Content-Disposition: form-data; name="userfile"; filename="abc.txt"     Content-Type: application/octet-stream     111222333     -----------------------------11454065798049615451989194362--     */    //2.拼接头    NSMutableString *headerString = [NSMutableString string];    //2.1 拼接第一行    [headerString appendFormat:@"--%@\r\n",kBoundaryUpload]; //2.1 拼接第二行 [headerString appendFormat:@"Content-Disposition: form-data; name=%@; filename=%@\r\n",serverFieldName,fileSaveName]; //2.3 拼接第三行 [headerString appendString:@"Content-Type: application/octet-stream\r\n\r\n"]; //2.4 将头部的字符串转成二进制 NSData *headerData = [headerString dataUsingEncoding:NSUTF8StringEncoding]; //2.5 拼接到dataM后面 [dataM appendData:headerData]; //3.拼接内容 [dataM appendData:fileData]; [dataM appendData:[@"\r\n" dataUsingEncoding:NSUTF8StringEncoding]]; //4.拼接尾巴 NSString *tailString = [NSString stringWithFormat:@"--%@--\r\n\r\n",kBoundaryUpload]; [dataM appendData:[tailString dataUsingEncoding:NSUTF8StringEncoding]]; return dataM.copy; }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36

3. 下载请求

- (NSURLSession *)downLoadSession{    if (_downLoadSession==nil) {        //开发中,就用这个        NSURLSessionConfiguration *defaultConfigration = [NSURLSessionConfiguration defaultSessionConfiguration];        /**            参数1:配置            参数2:代理            参数3:队列,如果我们写的是主队列,那么代理方法在主线程调用                    如果是通过 [[NSOperationQueue] alloc] init]那么代理方法在子线程调用                    nil 这相当于 [[NSOperationQueue] alloc] init]         */        _downLoadSession = [NSURLSession sessionWithConfiguration:defaultConfigration delegate:self delegateQueue:nil];    }    return _downLoadSession;}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
- (void)touchesBegan:(NSSet
*)touches withEvent:(UIEvent *)event{ //1.NSURL NSURL *url = [NSURL URLWithString:@"http://localhost/videos.zip"]; //2.下载我们为了设置代理,获取进度,自己创建session NSURLSession *downLoadSession = self.downLoadSession; //3.由downLoadSession发起下载任务 NSURLSessionDownloadTask *downLoadTask = [downLoadSession downloadTaskWithURL:url]; //4.resume [downLoadTask resume]; }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

三、AFNetworking3.0封装思路简析

1. AFN的内部中的RunLoop

AFN内部开了一条专门用来访问网络请求的线程,在这个开线程的方法中,他把方法和dispatch_once都用static修饰了下,以保证这个方法的安全性以及只开辟一块内存空间,而且保证他线程不死,在这个方法中他会调用另一个网络请求入口的方法

这里写图片描述

在这个入口方法中他会创建一个RunLoop,然后添加一个NSMachPort端口,目的是为了让他里面有Source(因为有了Source的RunLoop才能真正跑起来) 

然后启动RunLoop,通过RunLoop在里面不断的循环,不断的发送消息,让他做事情.

这里写图片描述

2. 基于NSURLSession的封装

AFHTTPSessionManager封装了HTTP请求的常见处理,包括GET/POST方法,同时还包括了解析服务器响应数据的方法

AFHTTPSessionManager的GET请求

- (NSURLSessionDataTask *)GET:(NSString *)URLString parameters:(id)parameters success:(void (^)(NSURLSessionDataTask *task, id responseObject))success failure:(void (^)(NSURLSessionDataTask *task, NSError *error))failure
  • 1
  • 2
  • 3
  • 4
  • 1
  • 2
  • 3
  • 4

AFHTTPSessionManager的POST请求

- (NSURLSessionDataTask *)POST:(NSString *)URLString parameters:(id)parameters success:(void (^)(NSURLSessionDataTask *task, id responseObject))success failure:(void (^)(NSURLSessionDataTask *task, NSError *error))failure
  • 1
  • 2
  • 3
  • 4
  • 1
  • 2
  • 3
  • 4

AFN解析相关

AFN在解析时候,默认解析的是JSON数据。如果想解析XML数据,就需要手动把responseSerializer 的值该掉

AFHTTPSessionManager *mgr = [AFHTTPSessionManager manager];mgr.responseSerializer = [AFXMLParserResponseSerializer serializer];
  • 1
  • 2
  • 1
  • 2

将方法的返回值类型也改成XML,然后自己解析。 

如果服务器返回的是普通的数据类型,这时就要告诉AFN用普通的数据类型来解析,服务器返回什么样,解析成什么样即可

AFHTTPSessionManager *mgr = [AFHTTPSessionManager manager];mgr.responseSerializer = [AFHTTPResponseSerializer serializer];

转载于:https://www.cnblogs.com/zxykit/p/6164074.html

你可能感兴趣的文章
大道至简:软件实践者的思想读后感
查看>>
Kiss MySQL goodbye for development and say hello to HSQLDB
查看>>
Python web多sitemap创建更新解决方案
查看>>
javase基础10
查看>>
Qt Font
查看>>
UILabel设置富文本格式显示
查看>>
[洛谷P3379]【模板】最近公共祖先(LCA)
查看>>
java程序——随机数求和
查看>>
HTML5的浏览器支持方案
查看>>
在Asp.Net MVC中使用Repeater控件
查看>>
应用程序已被安全设置阻止
查看>>
找球号(一)
查看>>
开发小计(3)
查看>>
[Codevs] 1001 舒适的路线
查看>>
Deep Learning相关
查看>>
MySQL 树形结构 根据指定节点 获取其所有父节点序列
查看>>
hdu_5773_The All-purpose Zero(LIS)
查看>>
流程控制之while循环
查看>>
JSONObject和JSONArray区别及基本用法
查看>>
java多线程例子
查看>>