AFNetworking到底做了什么?

Author Avatar
XibHe 11月 26, 2017
  • 在其它设备中阅读本文章

最近在对接一个demo,主要是调用一下SDK,实现一些功能。发现这个demo的网络请求部分是基于NSURLConnection做的一些简单调用。用起来感觉总是怪怪的,于是就想切换回自己一直在用的AFNetworking。结果,和我想的还是不太一致。同时,也暴露出一个严重的问题:对AFNetworking实现原理,到底做了什么?可以说是一窍不通。之前一直以为对AFNetworking很熟悉了,现在看来,也只是停留在调用AFHTTPSessionManager的表面。

NSURLSessionNSURLSessionDataTask这两个类是iOS做网络请求的核心类,而AFNetworking则是对其做了一系列封装,简化了使用系统原生API做网络请求的过程。

更新说明

更新记录:

  • 2017 年 11 月,第一版。
  • 2017 年 12 月,对具体的步骤进行归类整理。

AFNetworking调用是做了一层简单的封装,将请求时用到的各种参数在一个继承自NSObject的类中统一配置。如下,

+ (void)postWithUrl:(NSString*)url params:(NSDictionary*)params  success:(HttpSuccessBlock)success failure:(HttpFailureBlock)failure
{
    AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
    [manager.requestSerializer setValue:@"application/json; charset=UTF-8" forHTTPHeaderField:@"Content-Type"];
    [manager.requestSerializer setValue:@"gzip" forHTTPHeaderField:@"Accept-Encoding"];
    manager.requestSerializer.timeoutInterval = 20.f; //设置请求超时时间
    manager.responseSerializer = [AFJSONResponseSerializer serializer];
    manager.responseSerializer.acceptableContentTypes = [NSSet setWithObject:@"text/html"];
    [manager POST:url parameters:params progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {

        NSDictionary *bodyObjDic = [responseObject objectForKey:@"body"];
        CLog(@"bodyObjDic = %@",bodyObjDic);
        NSString *code = [bodyObjDic objectForKey:@"code"];
        CLog(@"url = %@,code = %@",url,code);
        if ([code isEqualToString:@"200"]) {
            if(success)
                success ([responseObject objectForKey:@"body"]);
        } else if(code == nil){
            NSError *error = [NSError errorWithDomain:@"请求错误" code:-1 userInfo:nil];
            if(failure)
                failure(error);
        }

    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        if([@"NSURLErrorDomain" isEqualToString:error.domain]){
            error = [NSError errorWithDomain:@"请监测您的网络环境" code:error.code  userInfo:nil];
        }
        if([@"NSCocoaErrorDomain" isEqualToString:error.domain]){
            error = [NSError errorWithDomain:@"服务器繁忙,请稍候重试" code:error.code userInfo:nil];
        }
        if(failure)
            failure(error);
    }];
}

再将所有用于请求的url都放在这个类的类别中,统一管理。如下,

/**
 注册接口
 */
+ (void)getRegistedWithParams:(NSDictionary*)params success:(HttpSuccessBlock)success failure:(HttpFailureBlock)failure
 {
     [self postWithUrl:[NSString stringWithFormat:@"%@",kILVBHost] params:params success:^(id JSON) {
        if(success){
            success(JSON);
        }
    } failure:^(NSError *error) {
        if(failure){
            failure(error);
        }
    }];
 }

demo在网络请求时,会将参数转换并设置到HTTPBody中,上面那种直接使用AFHTTPSessionManager进行POST请求的方式就不行,其无法在请求时将请求的参数设置到request的HTTPBody中。于是,尝试通过新建一个NSMutableURLRequest请求,通过设置它的HTTPBody到达目的。如下,

+ (void)postWithUrl:(NSString*)url params:(NSDictionary*)params  success:(HttpSuccessBlock)success failure:(HttpFailureBlock)failure
{
    AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
    [manager.requestSerializer setValue:@"application/json; charset=UTF-8" forHTTPHeaderField:@"Content-Type"];
    [manager.requestSerializer setValue:@"gzip" forHTTPHeaderField:@"Accept-Encoding"];
    manager.requestSerializer.timeoutInterval = 20.f; //设置请求超时时间
    manager.responseSerializer = [AFJSONResponseSerializer serializer];
    NSError *requestError = nil;
    NSMutableURLRequest *request = [manager.requestSerializer requestWithMethod:@"POST" URLString:url parameters:params error:&requestError];
    request.HTTPBody = [NSData data];
    [manager.session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
        CLog(@"data = %@,response = %@",data,response);
    }];
}

但请求时会报500的错误。看来还需要接着往深了抛,看看AFNetworking到底做了什么?

这里之所以会设置manager.requestSerializer为:

[manager.requestSerializer setValue:@"application/json; charset=UTF-8" forHTTPHeaderField:@"Content-Type"];
[manager.requestSerializer setValue:@"gzip" forHTTPHeaderField:@"Accept-Encoding"];

是将NSMutableURLRequestmanager.requestSerializer混为一谈了。

demo中通过NSMutableURLRequest设置相应的请求头的属性值,如下:

NSURL *URL = [NSURL URLWithString:url];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:URL];

if (data){
 [request setValue:[NSString stringWithFormat:@"%ld",(long)[data length]] forHTTPHeaderField:@"Content-Length"];
 [request setHTTPMethod:@"POST"];
 [request setValue:@"application/json; charset=UTF-8" forHTTPHeaderField:@"Content-Type"];
 [request setValue:@"gzip" forHTTPHeaderField:@"Accept-Encoding"];
 [request setHTTPBody:data];        
}

manager.requestSerializer用于设置AFHTTPRequestSerializer(请求参数解析类)的,之所以会报解析或者服务器先关错误,是由于没有设置网络请求的解析方式导致。而responseSerializer默认使用了JSON的解析方式,这也是为什么当使用AFN进行网络请求时,JSON会自动进行解析的原因。这里如果想进行默认的request和response序列化,就要在manager的默认设置完成之后,在开始进行网络访问前使用:

AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
manager.requestSerializer = [AFJSONRequestSerializer serializer];
manager.responseSerializer = [AFJSONResponseSerializer serializer];

即可实现返回数据的自动解析。

AFNetworking到底做了什么?

AFNetworking概述


图片所在原文链接

AF分为如下5个功能模块:

  • 网络通信模块(AFURLSessionManager、AFHTTPSessionManger)
  • 网络通信信息序列化/反序列化模块(Serialization)
  • 网络状态监听模块(Reachability)
  • 网络通信安全策略模块(Security)
  • 对于iOS UIKit库的扩展(UIKit)

AF3.x是基于NSURLSession来封装的。所以这个类围绕着NSURLSession做了一系列的上层封装。而其余的四个模块,均是为了配合AFURLSessionManager类的网络通信做一些必要的处理工作。如上图,所示。

其中AFHTTPSessionManager是继承于AFURLSessionManager的,我们一般做网络请求都是用这个类,但是它本身是没有做实事的,只是做了一些简单的封装,把请求逻辑分发给父类AFURLSessionManager去做。

以上内容原文链接

对外接口类AFHTTPSessionManager

AFHTTPSessionManager不做实事,只是提供了对外调用的接口。

  • 调用父类方法进行初始化
- (instancetype)initWithBaseURL:(NSURL *)url
           sessionConfiguration:(NSURLSessionConfiguration *)configuration
{
    self = [super initWithSessionConfiguration:configuration];
    if (!self) {
        return nil;
    }
    //....
    return self;
}
  • 类似网络请求方法中,调用父类方法拿到task,这个类仅仅是把得到的task,resume即可
 NSURLSessionDataTask *dataTask = [self dataTaskWithHTTPMethod:@"GET"                                                   URLString:URLString parameters:parameters uploadProgress:nil                                             downloadProgress:downloadProgress                                                        success:success                                                       failure:failure];
 // 开始任务
 [dataTask resume];
  • AFHTTPSessionManager还做了一件很重要的事,就是把传过来的参数,编码成我们请求时需要的request,并且传给父类去做网络请求。

NSURLSession, NSURLSessionDataTask

NSMutableURLRequest *request = [self.requestSerializer requestWithMethod:method URLString:[[NSURL URLWithString:URLString relativeToURL:self.baseURL] absoluteString] parameters:parameters error:&serializationError];

AFNetworking请求核心类:AFURLSessionManager

NSURLSessionDataTask,
AFHTTPSessionManager的初始化方法,触发了这个类所有的初始化
初始化方法:

- (instancetype)initWithSessionConfiguration:(NSURLSessionConfiguration *)configuration;
- (instancetype)initWithSessionConfiguration:(NSURLSessionConfiguration *)configuration {
    self = [super init];
    if (!self) {
        return nil;
    }

    if (!configuration) {
        configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
    }

    self.sessionConfiguration = configuration;

    self.operationQueue = [[NSOperationQueue alloc] init];
    // queue并发线程数为1,这个是代理回调的queue
    self.operationQueue.maxConcurrentOperationCount = 1;

    // 注意代理,代理的继承,实际上NSURLSession去判断了,你实现了哪个方法会去调用,包括子代理的方法。
    self.session = [NSURLSession sessionWithConfiguration:self.sessionConfiguration delegate:self delegateQueue:self.operationQueue];

    // 各种响应转码
    self.responseSerializer = [AFJSONResponseSerializer serializer];

    // ssl证书,是验证证书,还是公钥,还是不用
    self.securityPolicy = [AFSecurityPolicy defaultPolicy];

#if !TARGET_OS_WATCH
    self.reachabilityManager = [AFNetworkReachabilityManager sharedManager];
#endif

    // 设置存储NSURL,task与AFURLSessionManagerTaskDelegate的词典(重点,在AF中,每一个task都会被匹配一个AFURLSessionManagerTaskDelegate 来做task的delegate事件处理)
    self.mutableTaskDelegatesKeyedByTaskIdentifier = [[NSMutableDictionary alloc] init];

    // 设置AFURLSessionManagerTaskDelegate 词典的锁,确保词典在多线程访问时的线程安全
    self.lock = [[NSLock alloc] init];
    self.lock.name = AFURLSessionManagerLockName;

    // 为所管理的session的所有task设置完成块,此方法为生成session之后就调用
    [self.session getTasksWithCompletionHandler:^(NSArray *dataTasks, NSArray *uploadTasks, NSArray *downloadTasks) {

    // 置空处理
        for (NSURLSessionDataTask *task in dataTasks) {
            [self addDelegateForDataTask:task uploadProgress:nil downloadProgress:nil completionHandler:nil];
        }

        for (NSURLSessionUploadTask *uploadTask in uploadTasks) {
            [self addDelegateForUploadTask:uploadTask progress:nil completionHandler:nil];
        }

        for (NSURLSessionDownloadTask *downloadTask in downloadTasks) {
            [self addDelegateForDownloadTask:downloadTask progress:nil destination:nil completionHandler:nil];
        }
    }];

    return self;
}

这个方法初始化了一些我们后续需要用到的属性,其他的都很简单,唯一比较费解的两处可能是:

self.operationQueue.maxConcurrentOperationCount = 1;

[self.session getTasksWithCompletionHandler:^(NSArray *dataTasks, NSArray *uploadTasks, NSArray *downloadTasks) {
       //置空处理
 }];

我们首先来讲讲这两个操作的作用:

  • 第一是让回调的代理queue是串行的,即请求完成的task只能一个个被回调。

  • 第二是清空了session中所有task。

- (NSURLSessionDataTask *)dataTaskWithRequest:(NSURLRequest *)request
                               uploadProgress:(nullable void (^)(NSProgress *uploadProgress)) uploadProgressBlock
                             downloadProgress:(nullable void (^)(NSProgress *downloadProgress)) downloadProgressBlock
                            completionHandler:(nullable void (^)(NSURLResponse *response, id _Nullable responseObject,  NSError * _Nullable error))completionHandler {

    // 第一件事,创建NSURLSessionDataTask,里面适配了Ios8以下taskIdentifiers,函数创建task对象。
    __block NSURLSessionDataTask *dataTask = nil;

    // 其实现应该是因为iOS 8.0以下版本中会并发地创建多个task对象,而同步有没有做好,导致taskIdentifiers 不唯一…这边做了一个串行处理
    url_session_manager_create_task_safely(^{
        dataTask = [self.session dataTaskWithRequest:request];
    });

    [self addDelegateForDataTask:dataTask uploadProgress:uploadProgressBlock downloadProgress:downloadProgressBlock completionHandler:completionHandler];

    return dataTask;
}

类似这个类中很多方法这样的方法,这些方法主要做两件事:

  1. 调用session的方法,传request过去去生成task。注意这里调用了url_session_manager_create_task_safely函数去执行的Block,这个函数实现如下:
static void url_session_manager_create_task_safely(dispatch_block_t block) {
    if (NSFoundationVersionNumber < NSFoundationVersionNumber_With_Fixed_5871104061079552_bug) {
        dispatch_sync(url_session_manager_creation_queue(), block);
    } else {
      block();
    }
}

简单来讲就是为了适配iOS8以下task创建,其中taskIdentifiers属性不唯一,而这个属性是我们之后添加代理的key,它必须是唯一的。 所以这里做了一个判断,如果是iOS8以下,则用串行同步的方式去执行这个Block,也就是创建session。否则直接执行。

  1. 给每个task创建并对应一个AF的代理对象,这基本上是这个类的核心所在了,这个代理对象为其对应的“task做数据拼接及成功回调。

方法如下:

- (void)addDelegateForDataTask:(NSURLSessionDataTask *)dataTask
                uploadProgress:(nullable void (^)(NSProgress *uploadProgress)) uploadProgressBlock
              downloadProgress:(nullable void (^)(NSProgress *downloadProgress)) downloadProgressBlock
             completionHandler:(void (^)(NSURLResponse *response, id responseObject, NSError *error))completionHandler
{
    AFURLSessionManagerTaskDelegate *delegate = [[AFURLSessionManagerTaskDelegate alloc] init];
    // AFURLSessionManagerTaskDelegate与AFURLSessionManager建立相互关系
    delegate.manager = self;
    delegate.completionHandler = completionHandler;
    // 这个taskDescriptionForSessionTasks用来发送开始和挂起通知的时候会用到,就是用这个值来Post通知,来两者对应
    dataTask.taskDescription = self.taskDescriptionForSessionTasks;

    // 将AF delegate对象与 dataTask建立关系
    [self setDelegate:delegate forTask:dataTask];

    // 设置AF delegate的上传进度,下载进度块
    delegate.uploadProgressBlock = uploadProgressBlock;
    delegate.downloadProgressBlock = downloadProgressBlock;
}

AF delegate对象与dataTask建立关系

- (void)setDelegate:(AFURLSessionManagerTaskDelegate *)delegate
            forTask:(NSURLSessionTask *)task
{
    // 断言,如果没有这个参数,debug下crash在这
    NSParameterAssert(task);
    NSParameterAssert(delegate);

    // 加锁保证字典线程安全
    [self.lock lock];

    // 将AF delegate放入以taskIdentifier标记的字典中(同一个NSURLSession中的taskIdentifier是唯一的)
self.mutableTaskDelegatesKeyedByTaskIdentifier[@(task.taskIdentifier)] = delegate;

    // 为AF delegate 设置task 的progress监听
    [delegate setupProgressForTask:task];

    // 添加task开始和暂停的通知
    [self addNotificationObserverForTask:task];
    [self.lock unlock];
}

以上两个方法创建了一个AFURLSessionManagerTaskDelegate的代理,把这个代理和task的taskIdentifier一一对应,放到我们最早初始化的字典里,建立起映射。

我们把AFUrlSessionManager作为了所有的task的delegate。当我们请求网络的时候,这些代理开始调用了:

NSURLSessionDelegate:

- (void)URLSession:(NSURLSession *)session
didBecomeInvalidWithError:(NSError *)error;

- (void)URLSession:(NSURLSession *)session
didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge
 completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential *credential))completionHandler;

NSURLSessionTaskDelegate:

- (void)URLSession:(NSURLSession *)session
              task:(NSURLSessionTask *)task
willPerformHTTPRedirection:(NSHTTPURLResponse *)response
        newRequest:(NSURLRequest *)request
 completionHandler:(void (^)(NSURLRequest *))completionHandler;

- (void)URLSession:(NSURLSession *)session
              task:(NSURLSessionTask *)task
didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge
 completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential *credential))completionHandler;

- (void)URLSession:(NSURLSession *)session
              task:(NSURLSessionTask *)task
 needNewBodyStream:(void (^)(NSInputStream *bodyStream))completionHandler;

- (void)URLSession:(NSURLSession *)session
              task:(NSURLSessionTask *)task
   didSendBodyData:(int64_t)bytesSent
    totalBytesSent:(int64_t)totalBytesSent
totalBytesExpectedToSend:(int64_t)totalBytesExpectedToSend;

- (void)URLSession:(NSURLSession *)session
              task:(NSURLSessionTask *)task
didCompleteWithError:(NSError *)error;

NSURLSessionDataDelegate:

- (void)URLSession:(NSURLSession *)session
          dataTask:(NSURLSessionDataTask *)dataTask
didReceiveResponse:(NSURLResponse *)response
 completionHandler:(void (^)(NSURLSessionResponseDisposition disposition))completionHandler;

- (void)URLSession:(NSURLSession *)session
          dataTask:(NSURLSessionDataTask *)dataTask
didBecomeDownloadTask:(NSURLSessionDownloadTask *)downloadTask;

- (void)URLSession:(NSURLSession *)session
          dataTask:(NSURLSessionDataTask *)dataTask
    didReceiveData:(NSData *)data;

- (void)URLSession:(NSURLSession *)session
          dataTask:(NSURLSessionDataTask *)dataTask
 willCacheResponse:(NSCachedURLResponse *)proposedResponse
 completionHandler:(void (^)(NSCachedURLResponse *cachedResponse))completionHandler;

NSURLSessionDownloadDelegate:

- (void)URLSession:(NSURLSession *)session
      downloadTask:(NSURLSessionDownloadTask *)downloadTask
didFinishDownloadingToURL:(NSURL *)location;

- (void)URLSession:(NSURLSession *)session
      downloadTask:(NSURLSessionDownloadTask *)downloadTask
      didWriteData:(int64_t)bytesWritten
 totalBytesWritten:(int64_t)totalBytesWritten
totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite;

- (void)URLSession:(NSURLSession *)session
      downloadTask:(NSURLSessionDownloadTask *)downloadTask
 didResumeAtOffset:(int64_t)fileOffset
expectedTotalBytes:(int64_t)expectedTotalBytes;
  • AFURLSessionManager一共实现了如上所列举的一大堆NSUrlSession相关的代理。

  • 而只转发了其中3条到AF自定义的delegate中:

NSURLSessionTaskDelegate:

- (void)URLSession:(__unused NSURLSession *)session
              task:(NSURLSessionTask *)task
didCompleteWithError:(NSError *)error;

NSURLSessionDataTaskDelegate:

- (void)URLSession:(__unused NSURLSession *)session
          dataTask:(__unused NSURLSessionDataTask *)dataTask
    didReceiveData:(NSData *)data;

NSURLSessionDownloadTaskDelegate:

- (void)URLSession:(NSURLSession *)session
      downloadTask:(NSURLSessionDownloadTask *)downloadTask
didFinishDownloadingToURL:(NSURL *)location;

AFUrlSessionManager对这一大堆代理做了一些公共的处理,而转发到AF自定义代理的3条,则负责把每个task对应的数据回调出去。

总结一下,这些代理主要是做了一些额外的处理,并且调用了它的属性Block:

@interface AFURLSessionManager ()
@property (readwrite, nonatomic, copy) AFURLSessionDidBecomeInvalidBlock sessionDidBecomeInvalid;
@property (readwrite, nonatomic, copy) AFURLSessionDidReceiveAuthenticationChallengeBlock sessionDidReceiveAuthenticationChallenge;
@property (readwrite, nonatomic, copy) AFURLSessionDidFinishEventsForBackgroundURLSessionBlock didFinishEventsForBackgroundURLSession;
@end

等属性……

我们可以利用这些Block,做一些自定义的处理,Block会随着代理调用而被调用,这些代理帮我们做了一些类似数据分片、断点续传、https认证等工作

除此之外,有3个代理方法回调了我们的task的AF代理,包括请求完成的代理,收到数据的代理,以及下载完成的代理,以第一个为例:

- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error
{
   // 根据task去取我们一开始创建绑定的delegate
    AFURLSessionManagerTaskDelegate *delegate = [self delegateForTask:task];

    // delegate may be nil when completing a task in the background
    if (delegate) {
    // 把代理转发给我们绑定的delegate
        [delegate URLSession:session task:task didCompleteWithError:error];
    // 转发完移除delegate 
       [self removeDelegateForTask:task];
    }
    // 公用Block回调
    if (self.taskDidComplete) {
        self.taskDidComplete(session, task, error);
    }
}

通过我们之前设置的task和AF代理映射,去调用AF代理,并且把这个task从映射字典中移除。

接着就调用了AF的代理:(自定义代理3条中的一条)

// AF实现的代理!被从urlsession那转发到这
- (void)URLSession:(__unused NSURLSession *)session
              task:(NSURLSessionTask *)task
didCompleteWithError:(NSError *)error
{

 // 强引用self.manager,防止被提前释放;因为self.manager声明为weak,类似Block 
    __strong AFURLSessionManager *manager = self.manager;

    __block id responseObject = nil;

   // 用来存储一些相关信息,来发送通知用的
    __block NSMutableDictionary *userInfo = [NSMutableDictionary dictionary];
   // 存储responseSerializer响应解析对象
    userInfo[AFNetworkingTaskDidCompleteResponseSerializerKey] = manager.responseSerializer;

    // Performance Improvement from #2672
    // **注意这行代码的用法,感觉写的很Nice...把请求到的数据data传出去,然后就不要这个值了释放内存** 
    NSData *data = nil;
    if (self.mutableData) {
        data = [self.mutableData copy];
        //We no longer need the reference, so nil it out to gain back some memory.
        self.mutableData = nil;
    }

    // 继续给userinfo填数据
    if (self.downloadFileURL) {
        userInfo[AFNetworkingTaskDidCompleteAssetPathKey] = self.downloadFileURL;
    } else if (data) {
        userInfo[AFNetworkingTaskDidCompleteResponseDataKey] = data;
    }
    // 错误处理
    if (error) {
        userInfo[AFNetworkingTaskDidCompleteErrorKey] = error;

    // 可以自己自定义完成组 和自定义完成queue,完成回调
        dispatch_group_async(manager.completionGroup ?: url_session_manager_completion_group(), manager.completionQueue ?: dispatch_get_main_queue(), ^{
            if (self.completionHandler) {
                self.completionHandler(task.response, responseObject, error);
            }
     // 主线程中完成通知
            dispatch_async(dispatch_get_main_queue(), ^{
                [[NSNotificationCenter defaultCenter] postNotificationName:AFNetworkingTaskDidCompleteNotification object:task userInfo:userInfo];
            });
        });
    } else {
        dispatch_async(url_session_manager_processing_queue(), ^{
            NSError *serializationError = nil;

            // 解析数据
            responseObject = [manager.responseSerializer responseObjectForResponse:task.response data:data error:&serializationError];

            // 如果是下载文件,那么responseObject为下载的路径
            if (self.downloadFileURL) {
                responseObject = self.downloadFileURL;
            }

            // 写入userInfo
            if (responseObject) {
         userInfo[AFNetworkingTaskDidCompleteSerializedResponseKey] = responseObject;
            }
           // 如果解析错误
            if (serializationError) {
                userInfo[AFNetworkingTaskDidCompleteErrorKey] = serializationError;
            }
           // 回调结果
            dispatch_group_async(manager.completionGroup ?: url_session_manager_completion_group(), manager.completionQueue ?: dispatch_get_main_queue(), ^{
                if (self.completionHandler) {
                    self.completionHandler(task.response, responseObject, serializationError);
                }

                dispatch_async(dispatch_get_main_queue(), ^{
                    [[NSNotificationCenter defaultCenter] postNotificationName:AFNetworkingTaskDidCompleteNotification object:task userInfo:userInfo];
                });
            });
        });
    }
}

虽然这个方法有点长,但是它主要做了两件事:

  1. 调用responseSerializer按照我们设置的格式,解析请求到的数据。

  2. 用completionHandler把数据回调出去,至此数据回到了用户手中。

到这里,AF的整个主线流程就完了,当然,我们跳过了很多细节没有讲,比如responseSerializer的各种格式的解析过程,还有为了监听task的开始和挂起通知,所做的method swizzling,这里对iOS7的兼容问题的处理,算是相当精彩了。

以上内容原文链接

处理请求和响应:AFURLSerialization

对发出请求以及接收响应的过程进行序列化,这涉及到两个模块:

  • AFURLResponseSerialization
  • AFURLRequestSerialization

前者是处理响应的模块,将请求返回的数据解析成对应的格式。而后者的主要作用是修改请求(主要是 HTTP 请求)的头部,提供了一些语义明确的接口设置 HTTP 头部字段。
我们首先会对 AFURLResponseSerialization 进行简单的介绍,因为这个模块使用在 AFURLSessionManager 也就是核心类中,而后者 AFURLRequestSerialization* 主要用于 AFHTTPSessionManager** 中,因为它主要用于修改 HTTP 头部。

有关解析类的详情见原文:

处理请求和响应 AFURLSerialization(三)

小结

本来想自己写关于AFN的使用心得,但发现自己的水平有限,不能把AFN主要做了什么?它是如何实现网络请求和解析的?这些问题说明白。只能将大牛文章中的精彩内容粘贴出来,做了一个简短的整理。这里引述涂耀辉AFNetworking到底做了什么? (终)一文中所说的一句话:

AFNetworking中凝聚了太多大牛的思想,根本不是你看完几遍源码所能去议论的。

参考资料

如何使用 AFNetworking 3.0 设置 Request.HttpBody

AFNetworking到底做了什么?

AFNetworking到底做了什么?(二)

AFNetworking 概述(一)

处理请求和响应 AFURLSerialization(三)