AFNetworking封装思路简析

http://blog.csdn.net/qq_34101611/article/details/51698473

一、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 是 iOS 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<UITouch *> *)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];
时间: 2024-08-03 06:36:23

AFNetworking封装思路简析的相关文章

Linux 系统故障排查思路简析

处理linux系统故障的思路:    1.重视错误提示信息.    2.查阅日志文件 .message (系统日志) 服务的日志 error(应用日志)    3.分析,定位问题.    4.解决问题.    忘记root密码?        重置:centos5或者6    启动加载grub引导菜单时 按esc 找到当前系统引导选项.        按方向键找到需要的系统引导内核,按 "e" 进入编辑状态.        然后通过方向键选中带有kernel指令的行 继续按"

排序 -- 思路简析(一)

简介 本篇文章总结一下最近学习的排序算法,提炼出其思想及不同之处.有归并排序,快速排序,堆排序以及冒泡排序 归并排序(Merging Sort) 归并是指将两个或两个以上的有序表组合成一个新的有序表. 归并排序是指把无序的的待排序序列分解成若干个有序子序列,并把有序子序列合并为整体有序序列的过程. 长度为1的序列是有序的. 采用两两分解和归并的策略简单易行,这样的归并排序称为2-路归并排序. 归并排序的实现 public static void sort(int[] arr) { if (arr

[转载] Thrift原理简析(JAVA)

转载自http://shift-alt-ctrl.iteye.com/blog/1987416 Apache Thrift是一个跨语言的服务框架,本质上为RPC,同时具有序列化.发序列化机制:当我们开发的service需要开放出去的时候,就会遇到跨语言调用的问题,JAVA语言开发了一个UserService用来提供获取用户信息的服务,如果服务消费端有PHP/Python/C++等,我们不可能为所有的语言都适配出相应的调用方式,有时候我们会很无奈的使用Http来作为访问协议;但是如果服务消费端不能

.NET设计模式简析

首先,是设计模式的分类,我们知道,常用的设计模式共23种.但总体来说,设计模式氛围三大类: 创建型模式,共五种:工厂方法模式.抽象工厂模式.单列模式.建造者模式.原型模式. 结构型模式,共七种:适配器模式.装饰器模式.代理模式.外观模式.桥接模式.组合模式.享元模式. 行为型模式,共十一种:策略模式.模版方法模式.观察者模式.迭代子模式.责任链模式.命令模式.备忘录模式.转改模式.访问者模式.终结者模式.解释器模式. 另外还有并发型模式和线程池模式等. 介绍了分类,下面简单说下设计模式的六大原则

SpringMVC学习——概念、流程图、源码简析(一)

学习资料:开涛的<跟我学SpringMVC.pdf> 众所周知,springMVC是比较常用的web框架,通常整合spring使用.这里抛开spring,单纯的对springMVC做一下总结. 概念 HandlerMapping:处理器映射,对请求的URL进行映射为具体的处理器(如果有拦截器也包含拦截器,会将Handler和多个HandlerInterceptor封装为HandlerExecutionChain对象) HandlerAdapter:处理器适配器,适配不同类型的处理器,如Cont

面向对象多态简析

C#&C++多态问题简析 在学习C#面向对象时,对封装和继承基本上还是理解的,但是碰到多态,基本上就是记住了个父类引用指向子类对象,在很长时间内也是一直比较困惑.学习c++时,基本上算是有了一定了解.下面结合代码解释多态问题 首先是c#代码 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Duo

cgroup原理简析:进程调度

本篇来探究下cgroup对cpu的限制机制,前文提到过cgroup也是通过进程调度子系统来达到限制cpu的目的,因此需要了解下进程调度子系统. 因为是介绍cgroup的文章,因此只介绍进程调度中与cgroup密切关联的部分,详细完成的进程调度实现可参考进程调度的相关资料. 本文分为三个部分,首先介绍进程调度中的调度算法,在该基础上引入组调度,最后结合前面文章(cgroup原理简析:vfs文件系统)来说明上层通过echo pid >> tasks, echo n > cpu.shares等

WebGL 中 OpenGL ES 指令与 iOS 中 C 版指令的差异简析

太阳火神的美丽人生 (http://blog.csdn.net/opengl_es) 本文遵循"署名-非商业用途-保持一致"创作公用协议 转载请保留此句:太阳火神的美丽人生 -  本博客专注于 敏捷开发及移动和物联设备研究:iOS.Android.Html5.Arduino.pcDuino,否则,出自本博客的文章拒绝转载或再转载,谢谢合作. WebGL 中 OpenGL ES 指令与 iOS 中 C 版指令的差异,从整体上看,应该是 gl 前缀在 WebGL 版指令中的省略,举例对比如

简析Spring MVC 数据解析

简析Spring MVC 数据解析 特别说明:本文使用spring 版本为 4.1.3 常用数据提交方式: 1. form 表单提交数据 1.1 解析form表单数据(无图片等数据) 前端代码事例: <form action="test/entity" method="post"> 用户ID:<input type="text" name="userid"/><br> 用户名:<inp