做为iOS的开发者对于AFNetworking肯定不陌生,本文从代码流程的角度去窥探AFNetworking做了什么。
AFNetworking目录结构请参阅作者的这篇文章
由于NSURLSession只支持iOS 7以后,所以为了向下兼容我们看一下利用NSURLConnection创建请求的过程。
请求的创建与设置
我们以创建一个POST
请求过程为例:
1 | [[AFHTTPRequestOperationManager manager] POST:@"http://url" |
首先我们通过AFHTTPRequestSerializer
的requestWithMethod:URLString:parameters:
方法获取一个NSMutableURLRequest
跟进去:
1 | - (NSMutableURLRequest *)requestWithMethod:(NSString *)method |
继续跟进requestBySerializingRequest:withParameters:error:
方法:
1 | - (NSURLRequest *)requestBySerializingRequest:(NSURLRequest *)request |
创建完NSMutableURLRequest
后,通过AFHTTPRequestOperation
的HTTPRequestOperationWithRequest:success:failure:
方法,初始化成员变量以及请求成功和失败的block:
1 | - (AFHTTPRequestOperation *)HTTPRequestOperationWithRequest:(NSURLRequest *)request |
查看一下请求成功和失败的回调,跟进setCompletionBlockWithSuccess:failure:
方法:
1 | - (void)setCompletionBlockWithSuccess:(void (^)(AFHTTPRequestOperation *operation, id responseObject))success |
其中:
1 | dispatch_group_async(group, queue, ^{ |
最终AFURLConnectionOperation
类的completionBlcok
最终将执行如下代码:
1 | __weak __typeof(self)weakSelf = self; |
通过以上代码可以看出:
- 成功或失败的回调都是在主线程的队列中执行的
- 通过
dispatch_group_notify
方法确保,成功或失败的回调执行完成后才去执行,NSOperation
自己的完成block。
最后一步是将创建的AFHTTPRequestOperation
对象添加到operationQueue
中等待系统调度执行。
Operation的执行过程
接下来我们分析一下请求的执行过程:
首先,一个NSOperation
被添加进NSOperationQueue
中之后,当系统调度执行该Operation
时,首先从start
方法开始执行:
1 | // 将每一个connection放到同一个线程networkRequestThread中去执行 保证每一个请求的处理都是顺序执行的 |
我们看到在start
函数中将operationDidStart
方法加到networkRequestThread
的线程的runloop中去执行,而operationDidStart
方法将connection
和ouputStream
作为事件源填加到当前线程(networkRequestThread线程)的runloop中,然后runloop就会监听NSURLConnection
的处理回调,当事件发生时调用对应的代理去处理,在接收请求数据过程中使用了outputStream
,等到请求完成再将outputStream
中的数据传递给responseData
:
1 | - (void)connection:(NSURLConnection __unused *)connection |
整体的流程结构如下图:

需要注意的是:
- 首先请求operation添加到operationQueue中,这些operation的执行关系是并行的
- 每一个operation执行的任务是向networkRequestThread线程中添加任务operationDidStart,也就是说:[向networkRequestThread线程中添加任务operationDidStart的过程]是并行的
- 每一个operationDidStart任务的工作又是向networkRequestThread线程中添加connection和outputStream两个事件源
- 由于operationDidStart任务以及connection、outputStream事件源都是被添加到同一个networkRequestThread线程中的,所以这三者之间的执行关系是串行的,也就是说networkRequestThread线程的runloop的轮询的执行operationDidStart任务以及监听connection、outputStream事件源并做出处理这三者是串行的关系
延伸应用
设想以下场景:当进入一个界面的时候我们需要发送4个请求,而第4个请求的发出依赖于前3个请求的完成,这时候就需要对着几个请求进行一些同步操作,如果利用GCD的话我们首先想到的是利用dispatch group将前三个请求放到group中等到全部执行完成后再去执行第4个请求,再进一步我们如果想要记录前3个请求的完成情况的话又该怎么办呢,其实AFNetworking的AFURLConnectionOperation.m已经为我们提供了batchOfRequestOperations方法,为了能够对请求完成情况进行记录,使用了一些技巧请参见注释,方法如下:
1 | + (NSArray *)batchOfRequestOperations:(NSArray *)operations |