AFNetworking 实现下载请求的原理过程

实现下载的流程

  • 一 生成一个 NSMutableURLRequest
  • 二 创建 NSURLSessionTask
  • 创建 URLSessionTask过程解析
  • 代理方法调用过程
  • 这样设计的原因

一 生成一个 NSMutableURLRequest

   NSMutableURLRequest *request = [[AFHTTPRequestSerializer serializer] requestWithMethod:@"GET" URLString:requestUrl parameters:nil error:nil];
        [request setAllHTTPHeaderFields:[self requestHeader]];
        AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
        manager.requestSerializer.timeoutInterval = 15;

二 创建 NSURLSessionTask

        NSURLSessionTask *task = [manager downloadTaskWithRequest:request progress:^(NSProgress * _Nonnull downloadProgress) {
            
        } destination:^NSURL * _Nonnull(NSURL * _Nonnull targetPath, NSURLResponse * _Nonnull response) {
            NSURL *pathURL = [NSURL URLWithString:[@"file://" stringByAppendingString:filePath]];
            return pathURL;
        } completionHandler:^(NSURLResponse * _Nonnull response, NSURL * _Nullable filePath, NSError * _Nullable error) {
            if (!error) {
                [self performSelector:@selector(downloadFinish:) withObject:userInfo];
            } else {
                [self handleFailtureResponse:response error:error userInfo:userInfo];
                [self performSelector:@selector(requestFailed:) withObject:userInfo];
            }
        }] ;
        [task resume];

创建 URLSessionTask过程解析

生成 NSURLSessionDownloadTask

- (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
{
    NSURLSessionDownloadTask *downloadTask = [self.session downloadTaskWithRequest:request];
    
    [self addDelegateForDownloadTask:downloadTask progress:downloadProgressBlock destination:destination completionHandler:completionHandler];

    return downloadTask;
}

由于 NSURLSession的代理是AFURLSessionManager,所以系统的
网络请求相关的代理方法都是由 AFURLSessionManager 实现的,如图
AFNetworking 实现下载请求的原理过程_第1张图片

@interface AFURLSessionManager : NSObject 

addDelegateForDownloadTask 方法的实现

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

    if (destination) {
        delegate.downloadTaskDidFinishDownloading = ^NSURL * (NSURLSession * __unused session, NSURLSessionDownloadTask *task, NSURL *location) {
            return destination(location, task.response);
        };
    }

    downloadTask.taskDescription = self.taskDescriptionForSessionTasks;

    [self setDelegate:delegate forTask:downloadTask];

    delegate.downloadProgressBlock = downloadProgressBlock;
}

有上面代码可以看出,是创建了一个 AFURLSessionManagerTaskDelegate对象,把请求的完成回调,过程
回调,以及下载完成回调 downloadTaskDidFinishDownloading都传给了该AFURLSessionManagerTaskDelegate对象

又通过下面代码

- (void)setDelegate:(AFURLSessionManagerTaskDelegate *)delegate
            forTask:(NSURLSessionTask *)task
{
    NSParameterAssert(task);
    NSParameterAssert(delegate);

    [self.lock lock];
    self.mutableTaskDelegatesKeyedByTaskIdentifier[@(task.taskIdentifier)] = delegate;
    [self addNotificationObserverForTask:task];
    [self.lock unlock];
}

可以看出,创建的AFURLSessionManagerTaskDelegate对象被放在了 self.mutableTaskDelegatesKeyedByTaskIdentifier这个字典中,并且以
task.taskIdentifier作为key

代理方法调用过程

我们以 - (void)URLSession:(NSURLSession *)session
downloadTask:(NSURLSessionDownloadTask *)downloadTask
didFinishDownloadingToURL:(NSURL *)location 代理方法为例子

- (void)URLSession:(NSURLSession *)session
      downloadTask:(NSURLSessionDownloadTask *)downloadTask
didFinishDownloadingToURL:(NSURL *)location
{
    if ([location.pathExtension containsString:@"gif"]) {
        
    }
    
    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];
    }
}

由以上代码可以看出,在该代理方法中,先获取AFURLSessionManagerTaskDelegate对象,然后让AFURLSessionManagerTaskDelegate 对象执行和代理方法名相同的方法

获取AFURLSessionManagerTaskDelegate对象

- (AFURLSessionManagerTaskDelegate *)delegateForTask:(NSURLSessionTask *)task {
    NSParameterAssert(task);

    AFURLSessionManagerTaskDelegate *delegate = nil;
    [self.lock lock];
    delegate = self.mutableTaskDelegatesKeyedByTaskIdentifier[@(task.taskIdentifier)];
    [self.lock unlock];

    return delegate;
}

AFNetworking 实现下载请求的原理过程_第2张图片

这样设计的原因

AFNetworking这样设计,就可以是同一个AFURLSessionManager 对象
可以创建多个task,方便管理

你可能感兴趣的:(数据库,服务器,运维)