• AFNetworking网络请求详解


    一、AFURLSessionManager

            网络请求的核心类,主要作用有以下几点:

            1、线程安全的创建NSURLSession,并实现NSURLSessionDelegate

            2、设置responseSerializer(用于返回数据的解析,默认AFJSONResponseSerializer

                  设置securityPolicy(用于SSL证书,HTTPS访问安全管理)

                  设置completionQueue(请求完成返回数据时的队列,不设置默认回到主线程队列)

                  设置completionGroup(请求完成返回数据时的队列组,不设置会使用默认值)

                  设置reachabilityManager(用于网络状况的监控)

            3、生成各类NSURLSessionTask,以及设置各类Task的回调Block。

                  NSURLSessionDataTask、NSURLSessionUploadTask、NSURLSessionDownloadTask

            4、管理AFURLSessionManagerTaskDelegate,根据Task标识,把NSURLSessionDelegate

                  回调分发到具体的AFURLSessionManagerTaskDelegate对象中

    二、AFHTTPSessionManager

            是AFURLSessionManager子类,除了父类功能外,还有以下作用:

            1、设置requestSerializer

            2、根据不同请求方式生成NSURLSessionDataTask

    三、AFURLRequestSerialization

            是生成NSURLRequest的协议,主要针对AFHTTPSessionManager的requestSerializer

            AFURLRequestSerialization协议实现类为:AFHTTPRequestSerializer,除了帮我们生成

            NSURLRequest外,还可以设置stringEncoding、allowsCellularAccess、cachePolicy、

            HTTPRequestHeaders等一些请求相关的参数。

            AFHTTPRequestSerializer有2个子类(主要用于不同的`Content-Type`):

            AFJSONRequestSerializer(application/json)

            AFPropertyListRequestSerializer(application/x-plist)

            在处理multipart/form-data方式时,提供了方法:

    1. - (NSMutableURLRequest *)multipartFormRequestWithMethod:(NSString *)method
    2. URLString:(NSString *)URLString
    3. parameters:(nullable NSDictionary <NSString *, id> *)parameters
    4. constructingBodyWithBlock:(nullable void (^)(id formData))block
    5. error:(NSError * _Nullable __autoreleasing *)error;

            在constructingBodyWithBlock中提供了实现AFMultipartFormData协议的类用于添加参数

            AFMultipartFormData真正的实现类是AFStreamingMultipartFormData

    四、AFURLResponseSerialization

            是解析Response的协议,实现类为:AFHTTPResponseSerializer

            AFHTTPResponseSerializer有以下几个子类(用于解析不同的MIMEType):

            AFJSONResponseSerializerjson解析

            AFXMLParserResponseSerializerxml解析,返回NSXMLParser)

            AFXMLDocumentResponseSerializer(xml解析,返回NSXMLDocument)

            AFPropertyListResponseSerializer(plist解析)

            AFImageResponseSerializer(图片解析)

            AFCompoundResponseSerializer(组合解析,可以添加多个上面类,根据顺序解析)

    五、AFURLSessionManagerTaskDelegate

            真正的NSURLSessionDelegate实现类,用于管理Task的上传下载进度,完成回调等

    六、完整的网络请求流程

            1、准备工作。初始化AFHTTPSessionManager,并根据业务设置requestSerializer、

                  responseSerializer、baseUrl等

            2、创建Task,以自定义NSURLSessionDataTask为例:

    1. - (nullable NSURLSessionDataTask *)dataTaskWithHTTPMethod:(NSString *)method
    2. URLString:(NSString *)URLString
    3. parameters:(nullable id)parameters
    4. headers:(nullable NSDictionary <NSString *, NSString *> *)headers
    5. uploadProgress:(nullable void (^)(NSProgress *uploadProgress))uploadProgress
    6. downloadProgress:(nullable void (^)(NSProgress *downloadProgress))downloadProgress
    7. success:(nullable void (^)(NSURLSessionDataTask *task, id _Nullable responseObject))success
    8. failure:(nullable void (^)(NSURLSessionDataTask * _Nullable task, NSError *error))failure;

                  首页会根据我们设置的requestSerializer生成NSMutableURLRequest:

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

                  设置请求头:

    1. for (NSString *headerField in headers.keyEnumerator) {
    2. [request setValue:headers[headerField] forHTTPHeaderField:headerField];
    3. }

                  如果requestSerializer报错,就结束流程,从completionQueue回调出去,

                  如果requestSerializer成功,开始生成NSURLSessionDataTask:

    1. __block NSURLSessionDataTask *dataTask = nil;
    2. dataTask = [self dataTaskWithRequest:request
    3. uploadProgress:uploadProgress
    4. downloadProgress:downloadProgress
    5. completionHandler:^(NSURLResponse * __unused response, id responseObject, NSError *error) {
    6. if (error) {
    7. if (failure) {
    8. failure(dataTask, error);
    9. }
    10. } else {
    11. if (success) {
    12. success(dataTask, responseObject);
    13. }
    14. }
    15. }];

                  我们跟着生成的方法点进去看到,通过AFHTTPSessionManager.session生成Task,并且

                  创建Task的AFURLSessionManagerTaskDelegate和回调参数,同时根据Task的标识存储

                  Delegate到mutableTaskDelegatesKeyedByTaskIdentifier字典中

    1. NSURLSessionDataTask *dataTask = [self.session dataTaskWithRequest:request];
    2. [self addDelegateForDataTask:dataTask uploadProgress:uploadProgressBlock downloadProgress:downloadProgressBlock completionHandler:completionHandler];
    1. - (void)addDelegateForDataTask:(NSURLSessionDataTask *)dataTask
    2. uploadProgress:(nullable void (^)(NSProgress *uploadProgress)) uploadProgressBlock
    3. downloadProgress:(nullable void (^)(NSProgress *downloadProgress)) downloadProgressBlock
    4. completionHandler:(void (^)(NSURLResponse *response, id responseObject, NSError *error))completionHandler
    5. {
    6. AFURLSessionManagerTaskDelegate *delegate = [[AFURLSessionManagerTaskDelegate alloc] initWithTask:dataTask];
    7. delegate.manager = self;
    8. delegate.completionHandler = completionHandler;
    9. dataTask.taskDescription = self.taskDescriptionForSessionTasks;
    10. [self setDelegate:delegate forTask:dataTask];
    11. delegate.uploadProgressBlock = uploadProgressBlock;
    12. delegate.downloadProgressBlock = downloadProgressBlock;
    13. }
    1. - (void)setDelegate:(AFURLSessionManagerTaskDelegate *)delegate
    2. forTask:(NSURLSessionTask *)task
    3. {
    4. NSParameterAssert(task);
    5. NSParameterAssert(delegate);
    6. [self.lock lock];
    7. self.mutableTaskDelegatesKeyedByTaskIdentifier[@(task.taskIdentifier)] = delegate;
    8. [self addNotificationObserverForTask:task];
    9. [self.lock unlock];
    10. }

            3、启动Task,使用resume方法。而后通过NSURLSessionDelegate监听网络请求过程。我们

                  可以看到AFURLSessionManager实现的NSURLSessionDelegate方法中,首先根据task

                  标识获取对应的AFURLSessionManagerTaskDelegate,然后分发事件至具体的Delegate

                  类中。我们以didCompleteWithError回调看:

    1. - (void)URLSession:(NSURLSession *)session
    2. task:(NSURLSessionTask *)task
    3. didCompleteWithError:(NSError *)error
    4. {
    5. AFURLSessionManagerTaskDelegate *delegate = [self delegateForTask:task];
    6. // delegate may be nil when completing a task in the background
    7. if (delegate) {
    8. [delegate URLSession:session task:task didCompleteWithError:error];
    9. [self removeDelegateForTask:task];
    10. }
    11. if (self.taskDidComplete) {
    12. self.taskDidComplete(session, task, error);
    13. }
    14. }

            4、请求完成回调处理,实际是在AFURLSessionManagerTaskDelegate中实现的,通过阅读

                  代码实现可以看出如果请求出现错误,就回调到completionHandler,如果未出现错误,

                  首先获取manager的responseSerializer去解析返回内容,然后再回调出去

    1. - (void)URLSession:(__unused NSURLSession *)session
    2. task:(NSURLSessionTask *)task
    3. didCompleteWithError:(NSError *)error
    4. {
    5. error = objc_getAssociatedObject(task, AuthenticationChallengeErrorKey) ?: error;
    6. __strong AFURLSessionManager *manager = self.manager;
    7. __block id responseObject = nil;
    8. NSMutableDictionary *userInfo = [NSMutableDictionary dictionary];
    9. userInfo[AFNetworkingTaskDidCompleteResponseSerializerKey] = manager.responseSerializer;
    10. //Performance Improvement from #2672
    11. NSData *data = nil;
    12. if (self.mutableData) {
    13. data = [self.mutableData copy];
    14. //We no longer need the reference, so nil it out to gain back some memory.
    15. self.mutableData = nil;
    16. }
    17. #if AF_CAN_USE_AT_AVAILABLE && AF_CAN_INCLUDE_SESSION_TASK_METRICS
    18. if (@available(iOS 10, macOS 10.12, watchOS 3, tvOS 10, *)) {
    19. if (self.sessionTaskMetrics) {
    20. userInfo[AFNetworkingTaskDidCompleteSessionTaskMetrics] = self.sessionTaskMetrics;
    21. }
    22. }
    23. #endif
    24. if (self.downloadFileURL) {
    25. userInfo[AFNetworkingTaskDidCompleteAssetPathKey] = self.downloadFileURL;
    26. } else if (data) {
    27. userInfo[AFNetworkingTaskDidCompleteResponseDataKey] = data;
    28. }
    29. if (error) {
    30. userInfo[AFNetworkingTaskDidCompleteErrorKey] = error;
    31. dispatch_group_async(manager.completionGroup ?: url_session_manager_completion_group(), manager.completionQueue ?: dispatch_get_main_queue(), ^{
    32. if (self.completionHandler) {
    33. self.completionHandler(task.response, responseObject, error);
    34. }
    35. dispatch_async(dispatch_get_main_queue(), ^{
    36. [[NSNotificationCenter defaultCenter] postNotificationName:AFNetworkingTaskDidCompleteNotification object:task userInfo:userInfo];
    37. });
    38. });
    39. } else {
    40. dispatch_async(url_session_manager_processing_queue(), ^{
    41. NSError *serializationError = nil;
    42. responseObject = [manager.responseSerializer responseObjectForResponse:task.response data:data error:&serializationError];
    43. if (self.downloadFileURL) {
    44. responseObject = self.downloadFileURL;
    45. }
    46. if (responseObject) {
    47. userInfo[AFNetworkingTaskDidCompleteSerializedResponseKey] = responseObject;
    48. }
    49. if (serializationError) {
    50. userInfo[AFNetworkingTaskDidCompleteErrorKey] = serializationError;
    51. }
    52. dispatch_group_async(manager.completionGroup ?: url_session_manager_completion_group(), manager.completionQueue ?: dispatch_get_main_queue(), ^{
    53. if (self.completionHandler) {
    54. self.completionHandler(task.response, responseObject, serializationError);
    55. }
    56. dispatch_async(dispatch_get_main_queue(), ^{
    57. [[NSNotificationCenter defaultCenter] postNotificationName:AFNetworkingTaskDidCompleteNotification object:task userInfo:userInfo];
    58. });
    59. });
    60. });
    61. }
    62. }

  • 相关阅读:
    基于深度学习YOLOv8\YOLOv5的花卉识别鲜花识别检测分类系统设计
    VUE之axios总结
    python基于django的汽车租赁系统nodejs+vue+element
    SQL语言入门,语法,语句分类
    MT4深受投资者喜欢,anzo capital昂首资本认为这几个特点必不可少
    校园论坛设计(Java)——介绍篇
    【运行时的类型识别】
    论文阅读09——《Deep Fusion Clustering Network》
    [分布式]-Raft论文研读
    Spring Boot 整合 Redis,使用 RedisTemplate 客户端
  • 原文地址:https://blog.csdn.net/PeaksLee/article/details/126779290