• 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:@"--%@
    ",kBoundaryUpload];
        //2.1 拼接第二行
        [headerString appendFormat:@"Content-Disposition: form-data; name=%@; filename=%@
    ",serverFieldName,fileSaveName];
        //2.3 拼接第三行
        [headerString appendString:@"Content-Type: application/octet-stream
    
    "];
        //2.4 将头部的字符串转成二进制
        NSData *headerData = [headerString dataUsingEncoding:NSUTF8StringEncoding];
        //2.5 拼接到dataM后面
        [dataM appendData:headerData];
    
        //3.拼接内容
        [dataM appendData:fileData];
        [dataM appendData:[@"
    " dataUsingEncoding:NSUTF8StringEncoding]];
    
        //4.拼接尾巴
        NSString *tailString = [NSString stringWithFormat:@"--%@--
    
    ",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];
  • 相关阅读:
    20145总结
    2014515 总结
    2014514 总结
    20148总结
    20147总结
    20146总结
    20149总结
    2014512 总结
    2014513 总结
    【Visual Lisp】驱动器、目录、文件和注册表
  • 原文地址:https://www.cnblogs.com/zxykit/p/6164074.html
Copyright © 2020-2023  润新知