@CoDancer
2018-04-30T12:56:24.000000Z
字数 7154
阅读 960
网络 数据请求
先从AFNetworking框架从上往下看,可以看到它的对外接口主要有:
- (NSURLSessionDataTask *)GET:(NSString *)URLStringparameters:(id)parametersprogress:(void (^)(NSProgress * _Nonnull))downloadProgresssuccess:(void (^)(NSURLSessionDataTask * _Nonnull, id _Nullable))successfailure:(void (^)(NSURLSessionDataTask * _Nullable, NSError * _Nonnull))failure
当然这是通过AFHTTPSessionManager的对象去调用,返回的是NSURLSessionDataTask,在这个方法中,我们需要关心的有两个地方,一个是block事件的数据返回,一个是return返回的NSURLSessionDataTask的对象。
再往下面看一层是:
- (NSURLSessionDataTask *)dataTaskWithHTTPMethod:(NSString *)methodURLString:(NSString *)URLStringparameters:(id)parametersuploadProgress:(nullable void (^)(NSProgress *uploadProgress)) uploadProgressdownloadProgress:(nullable void (^)(NSProgress *downloadProgress)) downloadProgresssuccess:(void (^)(NSURLSessionDataTask *, id))successfailure:(void (^)(NSURLSessionDataTask *, NSError *))failure
在这个方法中有:
NSMutableURLRequest *request = [self.requestSerializer requestWithMethod:method URLString:[[NSURL URLWithString:URLString relativeToURL:self.baseURL] absoluteString] parameters:parameters error:&serializationError];
创建可改变的网络请求,在这个请求中设置
NSMutableURLRequest *mutableRequest = [[NSMutableURLRequest alloc] initWithURL:url];mutableRequest.HTTPMethod = method;
并且设置请求对象中头部字段HTTPHeaderField
[self setValue:[acceptLanguagesComponents componentsJoinedByString:@", "] forHTTPHeaderField:@"Accept-Language"];NSString *userAgent = nil;#if TARGET_OS_IOS// User-Agent Header; see http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.43userAgent = [NSString stringWithFormat:@"%@/%@ (%@; iOS %@; Scale/%0.2f)", [[NSBundle mainBundle] infoDictionary][(__bridge NSString *)kCFBundleExecutableKey] ?: [[NSBundle mainBundle] infoDictionary][(__bridge NSString *)kCFBundleIdentifierKey], [[NSBundle mainBundle] infoDictionary][@"CFBundleShortVersionString"] ?: [[NSBundle mainBundle] infoDictionary][(__bridge NSString *)kCFBundleVersionKey], [[UIDevice currentDevice] model], [[UIDevice currentDevice] systemVersion], [[UIScreen mainScreen] scale]];
>_mutableHTTPRequestHeaders:{"Accept-Language" = "en;q=1";"User-Agent" = "iOS Example/1.0 (iPhone; iOS 11.2; Scale/2.00)";}
初始化好网络请求对象后,然后把它当作参数传到方法中。
- (NSURLSessionDataTask *)dataTaskWithRequest:(NSURLRequest *)requestuploadProgress:(nullable void (^)(NSProgress *uploadProgress)) uploadProgressBlockdownloadProgress:(nullable void (^)(NSProgress *downloadProgress)) downloadProgressBlockcompletionHandler:(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;}
当然这个方法中返回的还是NSURLSessionDataTask的对象,但我们需要看的是block中的处理。
在这个方法中主要有两个通知
- (void)addNotificationObserverForTask:(NSURLSessionTask *)task {[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(taskDidResume:) name:AFNSURLSessionTaskDidResumeNotification object:task];[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(taskDidSuspend:) name:AFNSURLSessionTaskDidSuspendNotification object:task];}
监听恢复网络连接和暂停的事件。
而在创建AFHTTPSessionManager对象是的方法中有:
- (instancetype)initWithSessionConfiguration:(NSURLSessionConfiguration *)configuration
这里面主要有
self.session = [NSURLSession sessionWithConfiguration:self.sessionConfiguration delegate:self delegateQueue:self.operationQueue];[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];}}];
当然我们终于快看到了数据交接的底部了,就是AFURLSessionManager对象实现了 协议中的方法,而在实现这些方法中(举一个例子说明)
- (void)URLSession:(NSURLSession *)sessiontask:(NSURLSessionTask *)taskdidCompleteWithError:(NSError *)error{AFURLSessionManagerTaskDelegate *delegate = [self delegateForTask:task];// delegate may be nil when completing a task in the backgroundif (delegate) {[delegate URLSession:session task:task didCompleteWithError:error];[self removeDelegateForTask:task];}if (self.taskDidComplete) {self.taskDidComplete(session, task, error);}}
这个时候创建了一个AFURLSessionManagerTaskDelegate的对象,当然这个对象也实现了那些代理,而在这个类中,与原生IOS交接的方法中
- (void)URLSession:(__unused NSURLSession *)sessiontask:(NSURLSessionTask *)taskdidCompleteWithError:(NSError *)errordispatch_async(url_session_manager_processing_queue(), ^{NSError *serializationError = nil;responseObject = [manager.responseSerializer responseObjectForResponse:task.response data:data error:&serializationError];if (self.downloadFileURL) {responseObject = self.downloadFileURL;}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];});});});
这里我们看到dispatch_group_async
而它的作用是:可以实现监听一组任务是否完成,完成后得到通知执行其他的操作。
void dispatch_group_async(dispatch_group_t group,
dispatch_queue_t queue,
dispatch_block_t block);
group: 对应的任务组
queue: block任务执行的线程队列
在AFURLSessionManager对象中完成了队列后,就会获取主线程并把需要的数据通过回调传出去,当然也会通知这个任务完成的通知。
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(networkRequestDidFinish:) name:AFNetworkingTaskDidCompleteNotification object:nil];
- (void)networkRequestDidFinish:(NSNotification *)notification {if ([AFNetworkRequestFromNotification(notification) URL]) {[self decrementActivityCount];}}
这样就完成了数据的获取和回调。