AFN 2.0
AFHTTPRequestOperationManager
- (AFHTTPRequestOperation *)GET:(NSString *)URLString
parameters:(id)parameters
success:(void (^)(AFHTTPRequestOperation *operation, id responseObject))success
failure:(void (^)(AFHTTPRequestOperation *operation, NSError *error))failure
{
AFHTTPRequestOperation *operation = [self HTTPRequestOperationWithHTTPMethod:@"GET" URLString:URLString parameters:parameters success:success failure:failure];
[self.operationQueue addOperation:operation];
return operation;
}
就 get 方法而言, 它获取了一个 operation, 并将 operation 添加到self.operationQueue, 我们先不去看获取operation 的过程到底发生了什么, 首先很明确的是, 每次网络请求都会在一个非主线程中执行。
- (AFHTTPRequestOperation *)HTTPRequestOperationWithRequest:(NSURLRequest *)request
success:(void (^)(AFHTTPRequestOperation *operation, id responseObject))success
failure:(void (^)(AFHTTPRequestOperation *operation, NSError *error))failure
{
AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
operation.responseSerializer = self.responseSerializer;
operation.shouldUseCredentialStorage = self.shouldUseCredentialStorage;
operation.credential = self.credential;
operation.securityPolicy = self.securityPolicy;
[operation setCompletionBlockWithSuccess:success failure:failure];
operation.completionQueue = self.completionQueue;
operation.completionGroup = self.completionGroup;
return operation;
}
这段代码是获取 operation , 可以清晰的看出 AFHTTPRequestOperation 是 NSOperation 的一个子类, 成功和失败是在 自定义的 operation 中回调的.
再看 setCompletionBlockWithSuccess
发生了什么,
- (void)setCompletionBlockWithSuccess:(void (^)(AFHTTPRequestOperation *operation, id responseObject))success
failure:(void (^)(AFHTTPRequestOperation *operation, NSError *error))failure
{
self.completionBlock = ^{
// 由于代码过长, 具体参考 AFHTTPRequestOperation.m 107 行.
};
}
可以清晰看出, 在操作完成的时候在操作里面通过判断 error, 来确定返回成功还是失败。
这就是一个完成一个请求的回调, 请求的具体过成是在其父类 AFURLConnectionOperation 中完成的, AFURLConnectionOperation 继承自 NSOperation, 在重写的 start 方法中, 执行了operationDidStart 方法:
- (void)operationDidStart {
[self.lock lock];
if (![self isCancelled]) {
self.connection = [[NSURLConnection alloc] initWithRequest:self.request delegate:self startImmediately:NO];
NSRunLoop *runLoop = [NSRunLoop currentRunLoop];
for (NSString *runLoopMode in self.runLoopModes) {
[self.connection scheduleInRunLoop:runLoop forMode:runLoopMode];
[self.outputStream scheduleInRunLoop:runLoop forMode:runLoopMode];
}
[self.outputStream open];
[self.connection start];
}
[self.lock unlock];
dispatch_async(dispatch_get_main_queue(), ^{
[[NSNotificationCenter defaultCenter] postNotificationName:AFNetworkingOperationDidStartNotification object:self];
});
}
ok, 在operationDidStart方法中, 初始化了self.connection, 并执行了 start, 后面的处理主要依赖self.connection 代理的回调, 包括进度错误等, 那么具体流程大概就已经清楚。
这大概就是 AFHTTPRequestOperationManager 基于 NSURLConnection 的一次 get 网络请求, 其他同理。
为了保证每次的网络请求的回调都可以接收到, 使用唯一的线程, 通过启动 runloop, 来保证线程不退出, 具体: AFURLConnectionOperation.m 167 行。
AFN 3.0
AFURLSessionManager
NSURLSession对于文件下载做了优化。
(NSURLSessionDataTask *)GET:(NSString *)URLString
parameters:(id)parameters
progress:(void (^)(NSProgress * _Nonnull))downloadProgress
success:(void (^)(NSURLSessionDataTask * _Nonnull, id _Nullable))success
failure:(void (^)(NSURLSessionDataTask * _Nullable, NSError * _Nonnull))failure
{
NSURLSessionDataTask *dataTask = [self dataTaskWithHTTPMethod:@"GET"
URLString:URLString
parameters:parameters
uploadProgress:nil
downloadProgress:downloadProgress
success:success
failure:failure];
[dataTask resume];
return dataTask;
}
同样从 get 方法入手, 可以看出是获取到一个 NSURLSessionDataTask
, 并开始 task, 和afn2.0思路相似。
我们继续往里面看,
- (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 {
__block NSURLSessionDataTask *dataTask = nil;
url_session_manager_create_task_safely(^{
dataTask = [self.session dataTaskWithRequest:request];
});
[self addDelegateForDataTask:dataTask uploadProgress:uploadProgressBlock downloadProgress:downloadProgressBlock completionHandler:completionHandler];
return dataTask;
}
dataTask 在这一步已经获取到了, 下面的addDelegateForDataTask等是为了获取到进度和完成的回调。
self.operationQueue = [[NSOperationQueue alloc] init]; self.operationQueue.maxConcurrentOperationCount = 1;
self.session = [NSURLSession sessionWithConfiguration:self.sessionConfiguration delegate:self delegateQueue:self.operationQueue];
苹果 api 解释, 所以这里就不需要单例线程来保证回调, 因为他根本不会主动走 dealloc。
afn3.0 里的 task 就相当于 afn2.0 里面的 operation, 具体的实现思路大体相同。
网友评论