【AFNetWorking源码(二)AFURLSessionManger和AFHTTPSessionManager】

news2024/11/27 18:40:52

前言

学习了Mananger的初始化和以GET请求为例的过程,发现整个过程离不开AFHTTPSessionManager和AFURLSessionManger的某些方法。这两个是AFN的重要的网络通信模块内容,对它们作揖详细的学习。

AFURLSessionManagerAFHTTPSessionManager都是AFNetworking库中的两个类,用于处理网络请求和会话管理

如果只涉及到HTTP请求,一般会直接使用AFHTTPSessionManager进行操作。而AFURLSessionManager则提供了更底层的接口,适用于特定的定制需求或与NSURLSession相关的操作

1.1 AFURLSessionManger和AFHTTPSessionManager的关系

图解
在这里插入图片描述
首先AFURLSessionMangerAFHTTPSessionManager的父类,其中AFURLSessionManger内部还包含AFURLSessionManagerTaskDelegate_AFURLSessionTaskSwizzling

AFHTTPSessionManager本身是对网络请求做了一些简单的封装,请求的整个逻辑是分发给AFURLSessionManager或者其他类去做的;其内部管理自己的两种序列化工具,用来对请求和响应的数据做序列化;同时依赖于父类提供的保证安全,监控网络状态,实现发出HTTP请求的核心功能;

AFHTTPSessionManager也可以是AFURLSessionManager的基础上进一步封装,专门用于处理基于HTTP协议的网络请求,提供了更方便的HTTP请求方法和相关功能,如GET、POST等常见的HTTP方法,以及请求参数的设置、请求头的配置、数据解析等功能

1.2 AFURLSessionManager

1.2.1 AFURLSessionManger功能

AFURLSessionManager负责生成对应的NSURLSession的实例,管理AFNetworkReachabilityManagerAFSecurityPolicy,以此一来查看网络的连接情况,二来保证请求的安全,同时初始化生成一个AFJSONResponseSerializer的实例来序列化HTTP的响应结果;

遵守的协议

  • 点击发现他遵守了很多的协议
    请添加图片描述
    除此之外还提供了属性和方法用来完成其功能

关键属性

@property (nonatomic, strong) id <AFURLResponseSerialization> responseSerializer;
// 响应序列化


// SSL的安全策略
@property (nonatomic, strong) AFSecurityPolicy *securityPolicy;

/// 网络监控
@property (readwrite, nonatomic, strong) AFNetworkReachabilityManager *reachabilityManager;

概览

在这里插入图片描述

核心方法就是生成一个AFURLSessionManager的实例对象,上文在以GET请求为例的时候介绍了dataTaskWithRequest,其实还有uploadTaskWithRequest和 downloadTaskWithRequest和downloadTaskWithResumeData

uploadTaskWithRequest

点击发现uploadTaskWithRequest存在三个不同的请求方法

  • uploadTaskWithRequest:(NSURLRequest *)requestfromFile
  • (NSURLSessionUploadTask *)uploadTaskWithRequest:(NSURLRequest *)requestfromData
  • (NSURLSessionUploadTask *)uploadTaskWithStreamedRequest
/// 使用本地的文件请求创建一个NSURLSessionUploadTask
- (NSURLSessionUploadTask *)uploadTaskWithRequest:(NSURLRequest *)request
                                         fromFile:(NSURL *)fileURL
                                         progress:(void (^)(NSProgress *uploadProgress)) uploadProgressBlock
                                completionHandler:(void (^)(NSURLResponse *response, id responseObject, NSError *error))completionHandler
{
    /// 它调用了request和本地的文件URL路径创建了一个uploadTask
    NSURLSessionUploadTask *uploadTask = [self.session uploadTaskWithRequest:request fromFile:fileURL];
    
    /// 为该uploadTask太溺爱对应的代理 addDelegateForUploadTask
    if (uploadTask) {
        [self addDelegateForUploadTask:uploadTask
                              progress:uploadProgressBlock
                     completionHandler:completionHandler];
    }

    return uploadTask;
}

/// 根据指定的HTTP Body请求创建URLSessionUploadTask
- (NSURLSessionUploadTask *)uploadTaskWithRequest:(NSURLRequest *)request
                                         fromData:(NSData *)bodyData
                                         progress:(void (^)(NSProgress *uploadProgress)) uploadProgressBlock
                                completionHandler:(void (^)(NSURLResponse *response, id responseObject, NSError *error))completionHandler
{
    NSURLSessionUploadTask *uploadTask = [self.session uploadTaskWithRequest:request fromData:bodyData];
    
    [self addDelegateForUploadTask:uploadTask progress:uploadProgressBlock completionHandler:completionHandler];

    return uploadTask;
}
/// AFURLSessionManager的一个方法,用于创建一个基于流的上传任务。具体参数说明如下:
/// request:上传请求,即要上传的数据和上传地址。
/// uploadProgressBlock:上传进度回调,NSProgress对象用于获取上传进度信息。
/// completionHandler:上传完成后的回调,包含上传的响应、响应数据和错误信息。
- (NSURLSessionUploadTask *)uploadTaskWithStreamedRequest:(NSURLRequest *)request
                                                 progress:(void (^)(NSProgress *uploadProgress)) uploadProgressBlock
                                        completionHandler:(void (^)(NSURLResponse *response, id responseObject, NSError *error))completionHandler
{
    /// 使用这个方法创建的上传任务,数据是通过流的方式上传的,而不是直接读取文件或数据进行上传,因此适用于上传大文件或者流数据
    NSURLSessionUploadTask *uploadTask = [self.session uploadTaskWithStreamedRequest:request];

    [self addDelegateForUploadTask:uploadTask progress:uploadProgressBlock completionHandler:completionHandler];

    return uploadTask;
}

uploadTaskWithRequest根据不同的数据创建一个NSURLSessionUploadTask任务,最终都会走到AFURLSessionManageraddDelegateForUploadTask为对应的uploadTask设置代理;
请添加图片描述
解析:

/// uploadTask:要添加代理的上传任务。
/// uploadProgressBlock:上传进度回调,通过该回调可以获取上传的进度信息。
/// completionHandler:上传完成回调,包含上传的响应、响应数据和错误信息。
- (void)addDelegateForUploadTask:(NSURLSessionUploadTask *)uploadTask
                        progress:(void (^)(NSProgress *uploadProgress)) uploadProgressBlock
               completionHandler:(void (^)(NSURLResponse *response, id responseObject, NSError *error))completionHandler
{
    /// 创建了一个AFURLSessionManagerTaskDelegate对象作为上传任务的代理,将该代理与上传任务关联
    AFURLSessionManagerTaskDelegate *delegate = [[AFURLSessionManagerTaskDelegate alloc] initWithTask:uploadTask];
    delegate.manager = self;
    delegate.completionHandler = completionHandler;

    /// 将上传任务的描述设置为AFURLSessionManager的taskDescriptionForSessionTasks属性。
    uploadTask.taskDescription = self.taskDescriptionForSessionTasks;

    
    /// 最后,将代理对象设置为上传任务的代理,并设置上传进度回调和上传完成回调
    [self setDelegate:delegate forTask:uploadTask];

    delegate.uploadProgressBlock = uploadProgressBlock;
}

downloadTaskWithRequest

/// 根据指定的请求创建downloadTask
// 参数:
/// request:下载请求,即要下载的资源地址。
/// downloadProgressBlock:下载进度回调,用于获取下载进度信息。
/// destination:下载目标回调,用于指定下载文件的存储位置。
/// completionHandler:下载完成回调,包含下载的响应、文件路径和错误信息。
- (NSURLSessionDownloadTask *)downloadTaskWithRequest:(NSURLRequest *)request
                                             progress:(void (^)(NSProgress *downloadProgress)) downloadProgressBlock
                                          destination:(NSURL * (^)(NSURL *targetPath, NSURLResponse *response))destination
                                    completionHandler:(void (^)(NSURLResponse *response, NSURL *filePath, NSError *error))completionHandler
{
    /// 使用self.session创建一个NSURLSessionDownloadTask对象,即创建了一个下载任务。
    NSURLSessionDownloadTask *downloadTask = [self.session downloadTaskWithRequest:request];
    
    /// 调用addDelegateForDownloadTask:progress:destination:completionHandler:方法为下载任务添加代理
    [self addDelegateForDownloadTask:downloadTask progress:downloadProgressBlock destination:destination completionHandler:completionHandler];

    return downloadTask;
}

downloadTaskWithResumeData

///  创建重用数据的下载任务:根据已经下载的数据ResumeData创建下载任务继续进行下载
///  官方:用于创建一个带有断点续传功能的下载任务并添加相关的代理。

// 参数
///  resumeData:包含了之前下载任务的断点续传数据,用于恢复之前的下载进度。
/// downloadProgressBlock:下载进度回调,用于获取下载进度信息。
/// destination:下载目标回调,用于指定下载文件的存储位置。
/// completionHandler:下载完成回调,包含下载的响应、文件路径和错误信息。
- (NSURLSessionDownloadTask *)downloadTaskWithResumeData:(NSData *)resumeData
                                                progress:(void (^)(NSProgress *downloadProgress)) downloadProgressBlock
                                             destination:(NSURL * (^)(NSURL *targetPath, NSURLResponse *response))destination
                                       completionHandler:(void (^)(NSURLResponse *response, NSURL *filePath, NSError *error))completionHandler
{
    /// 首先使用self.session和提供的断点续传数据resumeData创建一个NSURLSessionDownloadTask对象,即创建了一个带有断点续传功能的下载任务。
    NSURLSessionDownloadTask *downloadTask = [self.session downloadTaskWithResumeData:resumeData];
    
    /// 调用addDelegateForDownloadTask:progress:destination:completionHandler:方法为下载任务添加代理,并传入下载进度回调、目标回调和完成回调。
    [self addDelegateForDownloadTask:downloadTask progress:downloadProgressBlock destination:destination completionHandler:completionHandler];

    return downloadTask;
}

download最终也会调用addDelegateForDownloadTask

解析:

/// 该方法 用于为下载任务添加代理和相关的回
/// downloadTask:要添加代理的下载任务。
/// downloadProgressBlock:下载进度回调,用于获取下载进度信息。
/// destination:下载目标回调,用于指定下载文件的存储位置。
/// completionHandler:下载完成回调,包含下载的响应、文件路径和错误信息。、
- (void)addDelegateForDownloadTask:(NSURLSessionDownloadTask *)downloadTask
                          progress:(void (^)(NSProgress *downloadProgress)) downloadProgressBlock
                       destination:(NSURL * (^)(NSURL *targetPath, NSURLResponse *response))destination
                 completionHandler:(void (^)(NSURLResponse *response, NSURL *filePath, NSError *error))completionHandler
{
    AFURLSessionManagerTaskDelegate *delegate = [[AFURLSessionManagerTaskDelegate alloc] initWithTask:downloadTask];
    delegate.manager = self;
    delegate.completionHandler = completionHandler;

    /// 如果提供了destination回调,则设置代理的downloadTaskDidFinishDownloading属性为一个代码块,该代码块接收NSURLSession、NSURLSessionDownloadTask和下载文件的临时位置作为参数,并通过调用destination回调来返回最终的下载文件位置
    if (destination) {
        delegate.downloadTaskDidFinishDownloading = ^NSURL * (NSURLSession * __unused session, NSURLSessionDownloadTask *task, NSURL *location) {
            return destination(location, task.response);
        };
    }

    /// 设置下载任务的taskDescription属性为self.taskDescriptionForSessionTasks,这是用于描述任务的字符串。
    downloadTask.taskDescription = self.taskDescriptionForSessionTasks;

    [self setDelegate:delegate forTask:downloadTask];

    delegate.downloadProgressBlock = downloadProgressBlock;
}

1.2.2 AFURLSessionMananger遵守的代理

在AFURLSessionMananger的实现文件里面可以发现NSURLSessionTaskDelegateNSURLSessionDataDelegate以及NSURLSessionDownloadDelegate

需要提前说明的是AFURLSessionManager对这些代理做了一些公共的处理,最终转发到自定义的代理AFURLSessionManagerTaskDelegate的3个代理方法中,用来负责把每个task对应的数据回调回去;

围绕他们三个展开学习
NSURLSessionDownloadDelegate

NSURLSessionDownloadDelegate的方法在AFURLSessionMananger实现了3个。

  • URLSession:downloadTask:didFinishDownloadingToURL:
    在下载任务完成后调用,提供下载文件的临时位置URL。可以在此方法中处理下载后的文件移动、保存等操作。
  • URLSession:downloadTask:didWriteData:totalBytesWritten:totalBytesExpectedToWrite:
    在下载任务进行中定期调用,提供下载进度的相关信息,包括已写入数据大小和总数据大小。可以在此方法中更新下载进度条等UI元素。
  • URLSession:downloadTask:didResumeAtOffset:expectedTotalBytes:
    在恢复下载任务时调用,提供已恢复的下载位置和预期的总字节数。
#pragma mark - NSURLSessionDownloadDelegate
/// 在下载任务完成后调用,提供下载文件的临时位置URL。可以在此方法中处理下载后的文件移动、保存等操作。
- (void)URLSession:(NSURLSession *)session
      downloadTask:(NSURLSessionDownloadTask *)downloadTask
didFinishDownloadingToURL:(NSURL *)location
{
// 转发代理
    AFURLSessionManagerTaskDelegate *delegate = [self delegateForTask:downloadTask];
    if (self.downloadTaskDidFinishDownloading) {
        NSURL *fileURL = self.downloadTaskDidFinishDownloading(session, downloadTask, location);
        if (fileURL) {
            delegate.downloadFileURL = fileURL;
            NSError *error = nil;
            
            if (![[NSFileManager defaultManager] moveItemAtURL:location toURL:fileURL error:&error]) {
                [[NSNotificationCenter defaultCenter] postNotificationName:AFURLSessionDownloadTaskDidFailToMoveFileNotification object:downloadTask userInfo:error.userInfo];
            } else {
                [[NSNotificationCenter defaultCenter] postNotificationName:AFURLSessionDownloadTaskDidMoveFileSuccessfullyNotification object:downloadTask userInfo:nil];
            }

            return;
        }
    }

    if (delegate) {
        [delegate URLSession:session downloadTask:downloadTask didFinishDownloadingToURL:location];
    }
}
/// 在下载任务进行中定期调用,提供下载进度的相关信息,包括已写入数据大小和总数据大小。可以在此方法中更新下载进度条等UI元素。
- (void)URLSession:(NSURLSession *)session
      downloadTask:(NSURLSessionDownloadTask *)downloadTask
      didWriteData:(int64_t)bytesWritten
 totalBytesWritten:(int64_t)totalBytesWritten
totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite
{
    // 转发代理

    AFURLSessionManagerTaskDelegate *delegate = [self delegateForTask:downloadTask];
    
    if (delegate) {
        [delegate URLSession:session downloadTask:downloadTask didWriteData:bytesWritten totalBytesWritten:totalBytesWritten totalBytesExpectedToWrite:totalBytesExpectedToWrite];
    }

    if (self.downloadTaskDidWriteData) {
        self.downloadTaskDidWriteData(session, downloadTask, bytesWritten, totalBytesWritten, totalBytesExpectedToWrite);
    }
}
/// 在恢复下载任务时调用,提供已恢复的下载位置和预期的总字节数
- (void)URLSession:(NSURLSession *)session
      downloadTask:(NSURLSessionDownloadTask *)downloadTask
 didResumeAtOffset:(int64_t)fileOffset
expectedTotalBytes:(int64_t)expectedTotalBytes
{
    // // 转发代理

    AFURLSessionManagerTaskDelegate *delegate = [self delegateForTask:downloadTask];
    
    if (delegate) {
        [delegate URLSession:session downloadTask:downloadTask didResumeAtOffset:fileOffset expectedTotalBytes:expectedTotalBytes];
    }

    if (self.downloadTaskDidResume) {
        self.downloadTaskDidResume(session, downloadTask, fileOffset, expectedTotalBytes);
    }
}

这三个代理方法最终都会进行代理转发,到AFURLSessionManagerTaskDelegate中,AF中的deleagate是需要对应每个task去私有化处理的对应看看AFURLSessionManagerTaskDelegate中的这三个代理方法都做了什么 吧:

ps:别跳转错了
请添加图片描述

#pragma mark - NSURLSessionDownloadDelegate

- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask
      didWriteData:(int64_t)bytesWritten
 totalBytesWritten:(int64_t)totalBytesWritten
totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite{
    
    // 更新当前下载进度
    self.downloadProgress.totalUnitCount = totalBytesExpectedToWrite;
    self.downloadProgress.completedUnitCount = totalBytesWritten;
}

- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask
 didResumeAtOffset:(int64_t)fileOffset
expectedTotalBytes:(int64_t)expectedTotalBytes{
    // 更新当前下载进度
    self.downloadProgress.totalUnitCount = expectedTotalBytes;
    self.downloadProgress.completedUnitCount = fileOffset;
}
/// ‼️下载完成调用
- (void)URLSession:(NSURLSession *)session
      downloadTask:(NSURLSessionDownloadTask *)downloadTask
didFinishDownloadingToURL:(NSURL *)location
{
    self.downloadFileURL = nil;

    if (self.downloadTaskDidFinishDownloading) {
        self.downloadFileURL = self.downloadTaskDidFinishDownloading(session, downloadTask, location);
        if (self.downloadFileURL) {
            NSError *fileManagerError = nil;

            if (![[NSFileManager defaultManager] moveItemAtURL:location toURL:self.downloadFileURL error:&fileManagerError]) {
                [[NSNotificationCenter defaultCenter] postNotificationName:AFURLSessionDownloadTaskDidFailToMoveFileNotification object:downloadTask userInfo:fileManagerError.userInfo];
            } else {
                [[NSNotificationCenter defaultCenter] postNotificationName:AFURLSessionDownloadTaskDidMoveFileSuccessfullyNotification object:downloadTask userInfo:nil];
            }
        }
    }
}

  • 在 ‼️ 下载完成时的调用代理方法中,AFURLSessionManagerAFURLSessionManagerTaskDelegate中都进行了文件路径的移动,而NSURlSession代理的下载路径是所有request公用的下载路径,设置之后所有的request都会下载到之前的那个路径。而AFURLSessionManagerTaskDelegate中对应到每一个task中,每一个task可以设置自己的下载路径;
  • 总结:这些代理方法在AFURLSessionManager中实现的时候都是对session做一个公共的处理,每一个不同的task进行特定的处理时,需要将代理转发到AFURLSessionManagerTaskDelegate中,在AFURLSessionManagerTaskDelegate的代理中实现;

1.3 AFURLSessionManagerTaskDelegate的作用

AFURLSessionManagerTaskDelegate 是 AFNetworking 框架中的一个类,用于处理 URLSessionTask 相关的代理回调。它作为 AFURLSessionManager 的任务代理,负责处理网络请求任务的进度、完成回调等操作。

具体来说,AFURLSessionManagerTaskDelegate 的主要作用包括:

  • 处理任务进度:通过设置 uploadProgressBlock 和 downloadProgressBlock 属性,可以监控上传任务和下载任务的进度,并在进度发生变化时执行相应的代码块。
  • 处理任务完成回调:在任务完成时,会执行 completionHandler 属性所指定的代码块,将任务的响应、响应数据和错误信息传递给回调函数,以便进一步处理任务的结果。
  • 处理下载任务的文件保存路径:对于下载任务,可以通过设置 downloadTaskDidFinishDownloading 属性,来指定任务完成后将文件保存的路径。
  • 管理任务与代理的关系:在创建任务时,会将任务与对应的 AFURLSessionManagerTaskDelegate 对象关联起来,以确保任务的代理回调能够正确处理。
  • 总的来说,AFURLSessionManagerTaskDelegate 扮演了一个中间角色,连接了 URLSessionTask 和 AFURLSessionManager 之间的交互,处理任务的进度、完成回调和其他相关操作,提供了更便捷的方式来管理和处理网络请求任务。

2. AFHTTPSessionManager

AFHTTPSessionManager本身是对网络请求做了一些简单的封装,请求的整个逻辑是分发给AFURLSessionManager或者其他类去做的;其内部管理自己的两种序列化工具,用来对请求和响应的数据做序列化;同时依赖于父类提供的保证安全,监控网络状态,实现发出HTTP请求的核心功能;

2.1 属性和接口

在这里插入图片描述
其实上一章已经很详细的说明了很多AFHTTPSessionManager的内容

AFHTTPSessionManager的一些方法的实现,初始化方法最终都会调用到AFURLSessionManager中的初始化方法完成sessionManager的初始化;

GET为例:

- (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对象
}

一是生成一个dataTask任务,二是调用resume开启请求;

该类的核心方法dataTaskWithHTTPMethod:URLString:parameters:headers:uploadProgress:downloadProgress:success:failure: 该方法是生成datatask,是AFHTTPSessionManager中的da taTaskWithHTTPMethod方法

在上一章也讲过! 很重要!

该方法做了两件事情:一是对请求参数进行序列化;二是调用dataTaskWithRequest方法生成后一个datatask任务;最终返回一个datatask;

- (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;

总结

到此,网络通讯模块所做的事情就到此,在该模块中主要的任务就是发起网络请求。分成AFURLSessionManger和 AFHTTPSessionManager两部分来做处理。 AFURLSessionManger是AFHTTPSessionManager的父类,其中AFURLSessionManger内部还包含AFURLSessionManagerTaskDelegate和_AFURLSessionTaskSwizzling;AFHTTPSessionManager本身是对网络请求做了一些简单的封装,请求的整个逻辑是分发给AFURLSessionManager或者其他类去做的;其内部管理自己的两种序列化工具,用来对请求和响应的数据做序列化;同时依赖于父类提供的保证安全,监控网络状态,实现发出HTTP请求的核心功能;

参考:AFN源码解析

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/537968.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

chatgpt赋能Python-mac电脑安装python

在Mac电脑上轻松安装Python Python是一种高级编程语言&#xff0c;常用于数据科学、机器学习和Web开发等领域。如果你是一名Mac电脑用户&#xff0c;那么安装Python将会让你受益匪浅。本文将提供详细的操作步骤&#xff0c;让你轻松安装Python并开始学习编程。 第一步&#x…

【Linux】进程地址空间(带你认清内存的本质)

&#x1f525;&#x1f525; 欢迎来到小林的博客&#xff01;&#xff01;       &#x1f6f0;️博客主页&#xff1a;✈️小林爱敲代码       &#x1f6f0;️博客专栏&#xff1a;✈️Linux之路       &#x1f6f0;️社区 :✈️ 进步学堂       &a…

Linux:chmod chown 权限管理

基础权限有以下三个 r 读 4 w 写 2 x 执行 1 - 无此权限 0 开头的第一个字母是这个的类型 d 目录 - 普通文件 l 链接文件 常见的三种 只不过今天不讲这个 从第二个字母开始看起 三个字母为一组 一共…

【EfficientDet】《EfficientDet:Scalable and Efficient Object Detection》

CVPR-2020 文章目录 1 Background and Motivation2 Related Work3 Advantages / Contributions4 Method4.1 BiFPN4.2 EfficientDet 5 Experiments5.1 Datasets5.2 EfficientDet for Object Detection5.3 EfficientDet for Semantic Segmentation5.4 Ablation Study 6 Conclusio…

RocketMQ你不得不了解的 Rebalance机制源码分析

这里是weihubeats,觉得文章不错可以关注公众号小奏技术&#xff0c;文章首发。拒绝营销号&#xff0c;拒绝标题党 RocketMQ版本 version: 5.1.0 RocketMQ中consumer消费模型 在了解RocketMQ的Rebalance机制之前&#xff0c;我们必须先简单了解下rocketmq的消费模型 我们知道…

chatgpt赋能Python-left函数_python

Left 函数在Python中的使用及其优点 在Python编程语言中&#xff0c;字符串处理是不可避免的任务。Python提供了许多内置函数来处理字符串&#xff0c;其中left()函数是其中一个非常重要的函数。本文将介绍left()函数的用法、优点和一些实例&#xff0c;以便更好的理解该函数。…

redis高级篇(2)---主从

一)搭建主从架构: 单节点Redis的并发能力是有限的&#xff0c;所以说要想进一步提高Redis的并发能力&#xff0c;就需要搭建主从集群&#xff0c;实现读写分离&#xff0c;因为对于Redis来说大部分都是读多写少的场景&#xff0c;更多的要进行读的压力&#xff0c;最基本都要是…

【Android学习专题】java基本语法和概念(学习记录)

学习记录来自菜鸟教程 Java 变量 Java 中主要有如下几种类型的变量 局部变量 在方法、构造方法或者语句块中定义的变量被称为局部变量。变量声明和初始化都是在方法中&#xff0c;方法结束后&#xff0c;变量就会自动销毁类变量&#xff08;静态变量&#xff09; 类变量也声…

chatgpt赋能Python-libreoffice_python宏

介绍 LibreOffice是一套免费开源的办公软件&#xff0c;其中包含一个强大的Python宏系统&#xff0c;可以使用Python编写脚本来增强办公软件的功能。本文将介绍LibreOffice Python宏是什么&#xff0c;如何使用Python编写宏&#xff0c;并提供一些示例&#xff0c;以便读者可以…

去付款--支付宝沙箱的简单测试

alipay-demo 进入开发者中心–开发工具–沙箱–设置公钥 搜索电脑网上支付–查看Demo–查看配置类–查看业务逻辑 我们的基础配置类主要是初始化我们的alipay客户端 真正去付款的时候是提交了一个form表单达到一个真正的支付jsp,java代码首先初始化我买的Alipay客户端&#xf…

瑞吉外卖 - 新增分类功能(11)

某马瑞吉外卖单体架构项目完整开发文档&#xff0c;基于 Spring Boot 2.7.11 JDK 11。预计 5 月 20 日前更新完成&#xff0c;有需要的胖友记得一键三连&#xff0c;关注主页 “瑞吉外卖” 专栏获取最新文章。 相关资料&#xff1a;https://pan.baidu.com/s/1rO1Vytcp67mcw-PD…

网安学习踩坑经验篇

回想学习网络安全一年来&#xff0c;踩了不少坑走了不少弯路&#xff0c;在此稍作总结&#xff0c;希望可以帮助那些想要入门 web 安全或者是想打CTF的同学们一些建议 坑点 先总结一下&#xff0c;我在学习中遇到的坑点 只看视频&#xff0c;眼高手低&#xff0c;不练习&…

【嵌入式Linux】设备树基本语法

设备树基本语法 1_总领-本期设备树视频要怎么讲&#xff1f;讲什么&#xff1f;_哔哩哔哩_bilibili 基本的 特殊的 中断控制 描述GIC控制器 时钟 CPU GPIO 个数&#xff0c;保留范围&#xff08;起始、长度&#xff09;&#xff0c;个数对应的名字 GPIO映射-这个脚被用了换一…

chatgpt赋能Python-numpy_归一化

NumPy归一化&#xff1a;理解数据规范化的重要性 什么是归一化&#xff1f; 在数据科学和机器学习中&#xff0c;归一化是预处理数据的一种常用技术。归一化是指将数据缩放到一个特定的范围内&#xff0c;通常是0到1或-1到1之间。 例如&#xff0c;我们可能比较一家医院的三…

渗透测试--5.3.使用john破解密码

前言 由于Linux是Internet最流行的服务器操作系统&#xff0c;因此它的安全性备受关注。这种安全主要靠口令实现。 Linux使用一个单向函数crypt&#xff08;&#xff09;来加密用户口令。单向函数crypt&#xff08;&#xff09;从数学原理上保证了从加密的密文得到加密前的明…

Java笔记_22(反射和动态代理)

Java笔记_22 一、反射1.1、反射的概述1.2、获取class对象的三种方式1.3、反射获取构造方法1.4、反射获取成员变量1.5、反射获取成员方法1.6、综合练习1.6.1、保存信息1.6.2、跟配置文件结合动态创建 一、反射 1.1、反射的概述 什么是反射? 反射允许对成员变量&#xff0c;成…

基于IC5000烧录器使用winIDEA烧写+调试程序(S32K324的软件烧写与调试)

目录 一、iSYSTEM简介二、如何使用iSYSTEM winIDEA烧写调试程序2.1 打开winIDEA&#xff1a;2.2 新建一个Workspace;2.3 硬件配置:2.4 选择CPU芯片型号&#xff1a;2.5 加载烧写文件&#xff1a;2.6 开始烧录程序&#xff1a;2.7 程序调试Debug&#xff1a;2.7.1 运行程序&…

PCL点云处理之单点选择的交互操作(一百六十七)

PCL点云处理之单点选择的交互操作(一百六十七) 一、效果展示二、实现代码一、效果展示 交互选择点,输出点信息,具体如下图所示 二、实现代码 #include <pcl/io/pcd_io.h> #include <pcl/point_types.h> #include <pcl/visualization/pcl_visu

Spring Cloud Alibaba(二)Nacos统一配置管理

目录 一、为什么需要配置中心 二、常用的配置中心 Nacos 的几个概念 三、Nacos配置中心的使用 &#xff08;一&#xff09;properties格式 1、导入依赖 2、在配置中心新建配置 3、修改配置文件名为bootstrap.yml 4、在微服务中添加nacos config服务地址的配置 5、测试…

chatgpt赋能Python-numpy精度

Numpy精度介绍 Numpy是一个用于进行科学计算的Python库&#xff0c;它提供了多维数组对象以及一系列用于操作数组的函数。Numpy的广泛使用使其成为数据科学中的重要组成部分。然而&#xff0c;Numpy中的精度问题却常常被忽视。 浮点数精度问题 在Numpy中&#xff0c;浮点数是…