[AFNetWorking source code 1]

Preface

Source code library part two.

AFNetworkingThis framework is a necessary third-party framework for iOS. Its efficient and concise API makes it the best iOS network request framework. It also makes network requests developed on iOS much easier. For native GET and POST requests, this framework AFNetworkingprovides A more convenient method facilitates client-server interaction.

This study is based on the AFNetworking4.0 library. Compared with 3.0, request headers are added, because when writing the project, I also found that whether it is my own backend or the native backend API, I need to write request headers.

The request header (Request Header)is a part of the information included in the HTTP request and is used to pass additional information and parameters about the request to the server.

1. Native network request sending method

Since NSURLConnectionit has been abandoned, it will be discussed here NSURLSession. Start with two request methods: GET and POST.

1.1 Native GET

step

  • Determine the request path
  • Create a variable request object request: can be omitted ((request header and request method [Get] are included by default), this step can be omitted).
  • Create session sessionobject
  • Create a request task based on the session object datatask(use dataTaskWithRequestor dataTaskWithURLmethod to create)
  • Execute Task task
  • After getting the response returned by the server, parse the data (XML, JSON, HTTP). If the returned data is in JSON format, use NSJSONSerializationthe

1.2 Native PSOT

  • For the native POST step, there is one more request header than GET, and the request object cannot be omitted in native POST because the request header needs to be added to the request.
  • Determine the requested path URL
  • Create a variable request object request: cannot be omitted - POST requests need to set request headers
  • Set the request header (the created request header needs to be serialized: ensure it is a data format recognized by the server) and the request method POST
  • Create session object
  • Create a request task datatask based on the session object - (via dataTaskWithRequest)
  • Execute Task
  • After getting the response returned by the server, parse the data (XML, JSON, HTTP). If the returned data is in JSON format, use NSJSONSerialization for deserialization.

2.AFN

2.1 Analysis of the basic architecture of AFN

Please add image description

The basic architecture of AFN4.0 and 3.0 has not changed much, and the whole is divided into file parts as shown in the figure.

  • NSURLSession: The main class of network requests, AFURLSessionManagerencapsulated NSURLSession, AFHTTPSessionManagerbut its subclasses, which have been optimized for HTTP requests
  • Reachability: Network status, AFNetworkReachabilityManagera class used to monitor the current network status
  • Security: Network security, HTTPS requests must be usedAFSecurityPolicy
  • Serialization: Serialization, AFURLRequestSerializationwhich is the serialization before the request AFURLResponseSerializationand the serialization of the result after the request is completed.
  • UIKit: Inside are some UIkit extensionsCategory

The relationship between classes is shown in the figure below.
Please add image description
The module division of AFN

  • Through the use and the above diagram, it can be seen that the entire AFN is centered around AFURLSessionManager.
  • AFNetWorkingIt is roughly divided into five major modules, the most core of which is the network communication module, which is mainly used to send and respond to requests.
  • AFNetworkReachabilityManagerIt is mainly used to monitor network status, and perform different operations and processing of requests and responses under different network statuses;
    in order to ensure the security of network requests, of course AFSecurityPolicy, the network security policy module is indispensable, and sessionmangeris initialized at the same time AFSecurityPolicyas network communication during initialization. Information request serialization class
  • The network communication information serialization module is divided into request serialization and response serialization. The request header and response header are encoded internally. When requesting, the request header is transcoded into a computer-recognizable format. When responding , Transcode the response result and send it back to the client
  • Some related extensions of the UIKit library, including UIImageView requests, UIButton requests, etc.

The entire step can also be understood as the following figure
Insert image description here

  • Network communication module (AFURLSessionManager, AFHTTPSessionManager)
  • Network status monitoring module (AFNetworkReachabilityManager)
  • Network communication security policy module (AFSecurityPolicy)
  • Network communication information serialization module (AFURLRequestSerialization, AFURLResponseSerialization)
  • Expansion of the iOS UIkit library (UIKit)

2.2 Take GET as an example to analyze the AFN usage process (AFHTTPSessionManager

Taking the GET request as an example, the following is the code of the request.

  • Generate the corresponding sessionManager;
  • Call the GET method to make a request;
  • The processing results in the GET callback include (task progress, result of successful request, result of failed request);

Please add image description

2.2.1 How AFN generates the corresponding sessionManager

AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];

Follow the illustrations step by step
Insert image description here

First initialize, and then call the methods of the parent class step by step. Let's look at it in sections.
Insert image description here

  • initialize, callinitWithBaseURL
+ (instancetype)manager {
    
    
    return [[[self class] alloc] initWithBaseURL:nil];
}
  • initWithBaseURLtransferinitWithBaseURL:(NSURL *)url sessionConfiguration:
- (instancetype)initWithBaseURL:(NSURL *)url {
    
    
    return [self initWithBaseURL:url sessionConfiguration:nil];
}
  • initWithBaseURL:(NSURL *)url sessionConfiguration:implementation analysis
- (instancetype)initWithBaseURL:(NSURL *)url
           sessionConfiguration:(NSURLSessionConfiguration *)configuration
{
    
    
// 最终都会调用父类的方法去实现初始化
    self = [super initWithSessionConfiguration:configuration];
    if (!self) {
    
    
        return nil;
    }

    // Ensure terminal slash for baseURL path, so that NSURL +URLWithString:relativeToURL: works as expected
    
    //条件判断了URL的路径是否具有长度大于0。它使用了[url path]方法来获取URL的路径,并通过length方法获取路径的长度。
    // [[url absoluteString] hasSuffix:@"/"]:这个条件判断了URL的绝对字符串表示是否以斜杠("/")结尾。它使用了[url absoluteString]方法获取URL的绝对字符串表示,并通过hasSuffix:方法检查字符串是否以斜杠结尾。
    
    if ([[url path] length] > 0 && ![[url absoluteString] hasSuffix:@"/"]) {
    
    

// 如果上述两个条件都为真(路径长度大于0且不以斜杠结尾),则执行以下代码块:
// url = [url URLByAppendingPathComponent:@""];:这行代码使用URLByAppendingPathComponent:方法将一个空路径组件追加到原始URL的路径末尾,从而确保URL的路径以斜杠结尾。

        url = [url URLByAppendingPathComponent:@""];
    }

    self.baseURL = url;

    self.requestSerializer = [AFHTTPRequestSerializer serializer];
    self.responseSerializer = [AFJSONResponseSerializer serializer];

    return self;
}
  • Overall, what this code does is it checks if the path of the URL is empty or does not end with a slash, and if the condition is not met, appends an empty path component to the end of the path to ensure that the path of the URL ends with a slash.
2.2.2. Initialization of AFURLSessionManager

From the last call above, self = [super initWithSessionConfiguration:configuration];we can see that AFHTTPSessionManagerthe initialization method at the end will eventually call the initialization method of its parent class initWitchSessionConfigurationand return a sessionManagermethod; then, we need to take a look at what the parent class, that is, AFURLSessionManagerhas done with its initialization.

- (instancetype)initWithSessionConfiguration:(NSURLSessionConfiguration *)configuration {
    
    
    self = [super init];
    if (!self) {
    
    
        return nil;
    }
   
    if (!configuration) {
    
    
        configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
        /*
         NSURLSessionConfiguration是用于配置NSURLSession的类。它提供了一系列属性和方法,用于定制和管理会话(session)的行为和特性。
         
         defaultSessionConfiguration:返回一个默认的会话配置,可用于创建默认的NSURLSession实例。
         */
    }

    self.sessionConfiguration = configuration;
    
    /// 初始化操作队列 并设置为串行队列 设置最大并发操作数
    self.operationQueue = [[NSOperationQueue alloc] init];
    
    /// ‼️队列的最大并发操作数设置为1,这里的并发操作数值的是回调代理的线程并发数。
    /// ‼️在多线程编程中,操作队列(operation queue)是用于管理操作(operation)的一种机制。操作队列可以用来异步执行一系列任务,并控制它们的并发性。
    /// 通过将最大并发操作数设置为 1,即 maxConcurrentOperationCount = 1,可以确保操作队列中的操作按顺序依次执行,而不会并发执行。这意味着每个操作将在上一个操作完成后才会开始执行。
    self.operationQueue.maxConcurrentOperationCount = 1;

    /// AFJSONResponseSerializer 用来序列化HTTP的响应
    self.responseSerializer = [AFJSONResponseSerializer serializer];

    /// 初始化SSI需要的 AFSecurityPolocy用来保证请求的安全性
    self.securityPolicy = [AFSecurityPolicy defaultPolicy];

#if !TARGET_OS_WATCH
    /// AFNetWorkRarchability Manager 查看网络连接情况
    self.reachabilityManager = [AFNetworkReachabilityManager sharedManager];
#endif

    /// ‼️初始化可变任务字典 任务task的id作为key 代理对象作为value
    /// self.mutableTaskDelegatesKeyedByTaskIdentifier = [[NSMutableDictionary alloc] init];是用来将每一个请求任务和自定义的AFURLSessionManagerTaskDelegate来建立映射的;(需要深入研究,代理和这里的关系,以及利用KVO的思想实现的相关)
    self.mutableTaskDelegatesKeyedByTaskIdentifier = [[NSMutableDictionary alloc] init];

    // 锁的初始化并命名
    self.lock = [[NSLock alloc] init];
    self.lock.name = AFURLSessionManagerLockName;

    /// ‼️ 在初始化的时候获取当前session中的所有task,为它们重新设置一遍代理;一般来说初始化的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;
}

  • Initialize the current session configuration, operation queue, lock, AFNetworkReachabilityManager, AFSecurityPolicyrequest serialization and variable task dictionary used to store tasks and other attributes;
  • Get all unfinished tasks in the current session and set agents for them;
  • requires attention! ️Place:
    • self.mutableTaskDelegatesKeyedByTaskIdentifierIs a mutable dictionary attribute used to associate a task identifier with the corresponding task delegate object
    • ️In multi-threaded programming, the operation queue is a mechanism used to manage operations. Operation queues can be used to execute a series of tasks asynchronously and control their concurrency.
    • By setting the maximum number of concurrent operations to 1, that is, maxConcurrentOperationCount = 1, you can ensure that the operations in the operation queue are executed in order and not concurrently. This means that each operation will not start executing until the previous operation has completed.
2.2.3 Three types of agents for tasks

For different tasks, how AFN completes network requests, uses getTasksWithCompletionHandler: method to obtain all tasks in the current session (session), and adds the corresponding task delegation object to each task.
Please add image description
The execution flow of the code is as follows:

  • Call getTasksWithCompletionHandler:a method that accepts a completion handler block as a parameter.
  • In the completion handler block, you will receive three parameters dataTasks, uploadTasksand downloadTasks, which respectively represent the data task, upload task and download task in the current session.
  • Use a for-inloop to iterate over the array, performing the following operations dataTasksfor each task of type:NSURLSessionDataTask
    • Call addDelegateForDataTask:uploadProgress:downloadProgress:completionHandler:the method, passing the task and corresponding parameters to the method.
    • This method will add a task delegate object for the data task and set callbacks for upload and download progress and task completion as needed.
  • Use a for-inloop to iterate over the array, performing similar operations uploadTasksfor each type of task:NSURLSessionUploadTask
    • Call addDelegateForUploadTask:progress:completionHandler:the method, passing the task and corresponding parameters to the method.
    • This method will add a task delegate object for the upload task, and set callbacks for upload progress and task completion as needed.
  • Use a for-inloop to iterate over the array, performing similar operations downloadTasksfor each type of task:NSURLSessionDownloadTask
    • Call addDelegateForDownloadTask:progress:destination:completionHandler:the method, passing the task and corresponding parameters to the method.
    • This method will add a task delegation object to the download task, and set callbacks for the download progress, file saving path, and task completion as needed.

Through getTasksWithCompletionHandlermethods, the appropriate task delegation object can be associated with each task, and the execution process of the task can be tracked and processed.

2.2.3.1 setDelegate method

View the source code of these three proxy methods. Please add image descriptionPlease add image description
Please add image description
By observing the implementation of the three proxy methods, they will be called in the end.setDelegate:(AFURLSessionManagerTaskDelegate *)delegate forTask:(NSURLSessionTask *)task

An implementation of a method that sets the corresponding task delegate object setDelegate:forTask:for a given .NSURLSessionTaskAFURLSessionManagerTaskDelegate

- (void)setDelegate:(AFURLSessionManagerTaskDelegate *)delegate
            forTask:(NSURLSessionTask *)task
{
    
    
/// 首先,通过使用 NSParameterAssert 宏进行断言,确保 task 和 delegate 参数非空。这是一种防御性编程的做法,以确保传入的参数符合预期,避免在后续使用过程中出现问题。
    NSParameterAssert(task);
    NSParameterAssert(delegate);
/// 接下来,通过调用 [self.lock lock] 来获取一个锁,确保在多线程环境中对 self.mutableTaskDelegatesKeyedByTaskIdentifier 字典的操作是线程安全的。
    [self.lock lock];
/// 将 delegate 任务委托对象与 task.taskIdentifier 任务标识符关联,并将其存储在 self.mutableTaskDelegatesKeyedByTaskIdentifier 字典中。使用 @(task.taskIdentifier) 将任务标识符转换为 NSNumber 对象作为字典的键。
    self.mutableTaskDelegatesKeyedByTaskIdentifier[@(task.taskIdentifier)] = delegate;
/// 调用 [self addNotificationObserverForTask:task] 方法,为任务添加通知观察者,以便在任务执行过程中获取相关通知,如任务完成、进度更新等。
    [self addNotificationObserverForTask:task];
/// 最后,通过调用 [self.lock unlock] 释放锁,确保线程安全的访问完成。
    [self.lock unlock];
}

The function of this method is to associate the specified task delegation object with the task and store it in the dictionary for subsequent use. This makes it easy to track and manage the delegate objects associated with each task for task status tracking, result processing, or other related operations.

2.2.4 Summary of how AFN generates the corresponding sessionManager

sessionAt this point, for all the current ones obtained during initialization task, the agents have been reset for them. Return to initWitchSessionConfigurationthe method to return the current object, return upward, and generate AFHTTPSessionManager *sessionMangean r object;

2.3 Process analysis of Mananger calling GET method

Let’s take GET as an example and look at the diagram first.
Insert image description here

2.3.1 Execution process of GET method

- (NSURLSessionDataTask *)GET:(NSString *)URLString
                   parameters:(nullable id)parameters
                      headers:(nullable NSDictionary <NSString *, NSString *> *)headers
                     progress:(nullable void (^)(NSProgress * _Nonnull))downloadProgress
                      success:(nullable void (^)(NSURLSessionDataTask * _Nonnull, id _Nullable))success
                      failure:(nullable void (^)(NSURLSessionDataTask * _Nullable, NSError * _Nonnull))failure
{
    
    
    /// 调用 dataTaskWithHTTPMethod:URLString:parameters:headers:uploadProgress:downloadProgress:success:failure: 方法,该方法创建一个 NSURLSessionDataTask 数据任务对象,用于执行指定的 HTTP GET 请求。将传入的参数传递给该方法以构建请求。

    NSURLSessionDataTask *dataTask = [self dataTaskWithHTTPMethod:@"GET"
                                                        URLString:URLString
                                                       parameters:parameters
                                                          headers:headers
                                                   uploadProgress:nil
                                                 downloadProgress:downloadProgress
                                                          success:success
                                                          failure:failure];
    
    /// 调用 [dataTask resume] 方法启动数据任务,使其开始执行。

    [dataTask resume];
    
    /// 返回数据任务对象 dataTask。
    return dataTask;
参数:
URLString:请求的URL值
parameters:根据需求的请求参数
headers:请求头
downloadProgress:更新下载进度的对象
success:任务成功后执行的Block对象
failure:任务失败后执行的Block对象
}

The execution flow of the code is as follows:

  • Receive the incoming URLString, parameters, headers, downloadProgress, successand failureparameters, which respectively represent the requested URL string, request parameters, request headers, download progress callback, success callback and failure callback.
  • Call dataTaskWithHTTPMethod:URLString:parameters:headers:uploadProgress:downloadProgress:success:failure:the method, which creates a NSURLSessionDataTaskdata task object for performing the specified HTTP GET request. Pass incoming parameters to this method to build the request.
  • Call [dataTask resume]the method to start the data task so that it can begin execution.
  • Returns the data task object dataTask.

Through this code, you can easily initiate a GET request, and you can customize the request URL, parameters, request headers, etc. by passing in parameters. At the same time, you can specify download progress callback, success callback and failure callback to handle the result and status of the request. Finally, the in the code [dataTask resume]starts the task, causing it to begin executing.

Generate dataTask method
  • dataTaskWithHTTPMethod:URLString:parameters:headers:uploadProgress:downloadProgress:success:failure: This method is to generate datatask and is the da method AFHTTPSessionManagerintaTaskWithHTTPMethod
- (NSURLSessionDataTask *)dataTaskWithHTTPMethod:(NSString *)method
                                       URLString:(NSString *)URLString
                                      parameters:(nullable id)parameters
                                         headers:(nullable NSDictionary <NSString *, NSString *> *)headers
                                  uploadProgress:(nullable void (^)(NSProgress *uploadProgress)) uploadProgress
                                downloadProgress:(nullable void (^)(NSProgress *downloadProgress)) downloadProgress
                                         success:(nullable void (^)(NSURLSessionDataTask *task, id _Nullable responseObject))success
                                         failure:(nullable void (^)(NSURLSessionDataTask * _Nullable task, NSError *error))failure
{
    
    
    NSError *serializationError = nil;
    
    /// 使用 `self.requestSerializer` 对象根据传入的参数构建一个 `NSMutableURLRequest` 可变请求对象。
    /// self.requestSerializer:请求序列化器
    /// ‼️‼️ 需要点进去的方法1
    NSMutableURLRequest *request = [self.requestSerializer requestWithMethod:method URLString:[[NSURL URLWithString:URLString relativeToURL:self.baseURL] absoluteString] parameters:parameters error:&serializationError];
    for (NSString *headerField in headers.keyEnumerator) {
    
    
        [request setValue:headers[headerField] forHTTPHeaderField:headerField];
    }

///  // 如果在构建请求过程中出现了 `serializationError` 错误,即请求参数序列化错误,则会执行相应的错误处理逻辑。
    if (serializationError) {
    
    
        if (failure) {
    
    
       /// 如果存在 `failure` 失败回调,则将错误通过异步方式回调到主队列上。
            dispatch_async(self.completionQueue ?: dispatch_get_main_queue(), ^{
    
    
                failure(nil, serializationError);
            });
        }

        return nil;
    }
/// 创建一个 `NSURLSessionDataTask` 数据任务对象
    __block NSURLSessionDataTask *dataTask = nil;
	/// 并调用 `dataTaskWithRequest:uploadProgress:downloadProgress:completionHandler:` 方法来配置任务的上传进度回调、下载进度回调和完成处理程序块。
	// ‼️ 需要点进去的方法2
    dataTask = [self dataTaskWithRequest:request
                          uploadProgress:uploadProgress
                        downloadProgress:downloadProgress
                       completionHandler:^(NSURLResponse * __unused response, id responseObject, NSError *error) {
    
    
        if (error) {
    
    
            if (failure) {
    
    
                failure(dataTask, error);
            }
        } else {
    
    
            if (success) {
    
    
                success(dataTask, responseObject);
            }
        }
    }];

    return dataTask;
}

dataTaskWithHTTPMethod:URLString:parameters:headers:uploadProgress:downloadProgress:success:failure:implementation of the method. This method is used to create a NSURLSessionDataTaskdata task object and configure the relevant parameters of the request.

The execution flow of the code is as follows:

  • Receive the incoming method, URLString, parameters, headers, uploadProgress, downloadProgress, successand failureparameters, which respectively represent the requested HTTP method, URL string, request parameters, request header, upload progress callback, download progress callback, success callback and failure callback.
  • Use the object to construct a mutable request object self.requestSerializerbased on the parameters passed in . NSMutableURLRequestThe requested URL will be spliced ​​and converted according to URLStringand . self.baseURLThe request parameters and error object will be requestWithMethod:URLString:parameters:error:returned by the method.
  • Traverse headersthe key-value pairs in the dictionary, use the key as the request header field, and the value as the request header value, and setValue:forHTTPHeaderField:set it to the request object through the method.
  • If an error occurs during the construction of the request serializationError, that is, a request parameter serialization error, the corresponding error handling logic will be executed. If there is failurea failure callback, the error will be called back to the main queue asynchronously.
  • Create a NSURLSessionDataTaskData Task object and call dataTaskWithRequest:uploadProgress:downloadProgress:completionHandler:the method to configure the task's upload progress callback, download progress callback, and completion handler blocks.
  • Returns the data task object dataTask.

In this method we need to check two methods, which I have marked.

  • One is requestWithMethodserialization processing
    • Reasons for serialization processing: HTTP network requests are based on network transmission of byte streams. Serialization can convert an object into a byte encoding to facilitate transmission on the network or other storage processing. When used, Deserialize it; to put it simply, for the sake of unification , we can use our own methods to save objects, but at the bottom level we only provide a mechanism to save the object state. Therefore, we need to serialize when storing to keep it consistent with the provided, and deserialize it when reading to get the form we want;
  • One is to dataTaskWithRequestgenerate data tasks

requestWithMethod: perform serialization processing

- (NSMutableURLRequest *)requestWithMethod:(NSString *)method
                                 URLString:(NSString *)URLString
                                parameters:(id)parameters
                                     error:(NSError *__autoreleasing *)error
{
    
    
/// 首先进行参数断言,确保传入的 method 和 URLString 不为 nil
    NSParameterAssert(method);
    NSParameterAssert(URLString);
/// 使用 NSURL 的 URLWithString: 方法将 URLString 转换为 NSURL 对象,然后进行参数断言,确保 url 不为 nil。
    NSURL *url = [NSURL URLWithString:URLString];

    NSParameterAssert(url);
/// 创建一个可变的 NSMutableURLRequest 请求对象,使用 initWithURL: 方法将 url 作为初始化参数,并将 method 赋值给请求对象的 HTTPMethod 属性。
    NSMutableURLRequest *mutableRequest = [[NSMutableURLRequest alloc] initWithURL:url];
    mutableRequest.HTTPMethod = method;
///遍历 AFHTTPRequestSerializerObservedKeyPaths() 方法返回的被观察的键路径,通过ketPath检查 self.mutableObservedChangedKeyPaths 是否包含该键路径,如果包含,则将 self 对象的对应键路径的值设置为请求对象的对应键路径的值。存到mutableRequest中
    for (NSString *keyPath in AFHTTPRequestSerializerObservedKeyPaths()) {
    
    
        if ([self.mutableObservedChangedKeyPaths containsObject:keyPath]) {
    
    
            [mutableRequest setValue:[self valueForKeyPath:keyPath] forKey:keyPath];
        }
    }

/// 调用 requestBySerializingRequest:withParameters:error: 方法,将请求对象和参数进行序列化,返回一个经过序列化处理的请求对象。如果出现错误,会将错误对象赋值给传入的 error 参数。

    mutableRequest = [[self requestBySerializingRequest:mutableRequest withParameters:parameters error:error] mutableCopy];
    ///mutableCopy: 将序列化后的请求对象转换为可变的副本,并返回该对象。

	return mutableRequest;
}

dataTaskWithRequest: Generate a datatask 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 {
    
    

/// 接收一个 NSURLRequest 对象作为请求参数,并使用该请求对象创建一个 NSURLSessionDataTask 对象,即 dataTask。
    NSURLSessionDataTask *dataTask = [self.session dataTaskWithRequest:request];

/// 调用 self 对象的 addDelegateForDataTask:uploadProgress:downloadProgress:completionHandler: 方法,为 dataTask 添加代理、上传进度回调、下载进度回调和完成处理块。这些参数分别是 uploadProgressBlock、downloadProgressBlock 和 completionHandler。
    [self addDelegateForDataTask:dataTask uploadProgress:uploadProgressBlock downloadProgress:downloadProgressBlock completionHandler:completionHandler];

    return dataTask;
}

AFURLSessionManagerThe implementation of the class dataTaskWithRequest:uploadProgress:downloadProgress:completionHandler:method. This method is used to create an NSURLSessionDataTaskobject and add a proxy and related progress callbacks and completion handling blocks to the task.

completionHandler

Please add image description

  • completionHandlerIs a callback closure used to process the results returned after the network request is completed. It is defined as(nullable void (^)(NSURLResponse *response, id _Nullable responseObject, NSError * _Nullable error))
  • Where responseis the response object of the request, responseObjectis the response body data (can be NSData, NSDictionary, etc.), erroris the error message that occurs during the request process, such as network unavailability, request timeout, etc.
  • In dataTaskWithRequest:uploadProgress:downloadProgress:completionHandler:, when the network request is completed, this closure will be called to process the request result.

Summarize

After completing the above processing, the generated dataTask is finally returned to the GET method, so that we finally get the task in GET that we can send the request to, and finally call the system method [dataTask resume]; initiate a network request;

AFURLSessionManager and the many proxies it complies with are called when we make network requests. Next, we will learn about AFURLSessionManager and its proxy parsing.

Guess you like

Origin blog.csdn.net/weixin_61639290/article/details/130692962