AFNetworking源码分析之NSURLSession

这个模块主要包括下面两个类

AFURLSessionManager
AFHTTPSessionManager

AFHTTPSessionManager继承自AFURLSessionManager,通常我们使用AFNetworking时,会像下面这样

    NSString *urlStr = @"https://api.douban.com/v2/movie/top250";
    NSDictionary *dic = @{@"start":@(1),
                          @"count":@(5)
                          };
    AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
//    manager.requestSerializer.timeoutInterval = 5;
    [manager GET:urlStr parameters:dic progress:^(NSProgress * _Nonnull downloadProgress) {
        
    } success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        NSLog(@"success");
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        
    }];

这一段代码AFN内部做了什么呢?

初始化

 AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];

这一行代码主要是做了初始化的操作,源码如下

- (instancetype)initWithBaseURL:(NSURL *)url
           sessionConfiguration:(NSURLSessionConfiguration *)configuration
{
    // 1、调用父类(AFURLSessionManager)初始化方法
    self = [super initWithSessionConfiguration:configuration];
    if (!self) {
        return nil;
    }

    // Ensure terminal slash for baseURL path, so that NSURL +URLWithString:relativeToURL: works as expected
    // 2、url有值且没有‘/’,那么在url的末尾添加‘/’
    if ([[url path] length] > 0 && ![[url absoluteString] hasSuffix:@"/"]) {
        url = [url URLByAppendingPathComponent:@""];
    }

    self.baseURL = url;
    // 3、给requestSerializer、responseSerializer设置默认值
    self.requestSerializer = [AFHTTPRequestSerializer serializer];
    self.responseSerializer = [AFJSONResponseSerializer serializer];

    return self;
}

这里我们主要讨论下一父类的初始化都做了些什么事情
1、初始化session
2、给manager的属性设置初始值

初始化session,defaultSessionConfiguration

self.session = [NSURLSession sessionWithConfiguration:self.sessionConfiguration delegate:self delegateQueue:self.operationQueue];

初始属性

    // 默认为json解析
    self.responseSerializer = [AFJSONResponseSerializer serializer];

    // 设置默认证书 无条件信任证书https认证
    self.securityPolicy = [AFSecurityPolicy defaultPolicy];

#if !TARGET_OS_WATCH
    // 网络状态监听
    self.reachabilityManager = [AFNetworkReachabilityManager sharedManager];
#endif

    // delegate= value taskid = key
    //可变字典,key是NSURLSessionTask的唯一NSUInteger类型标识,value是对应的AFURLSessionManagerTaskDelgate对象
    self.mutableTaskDelegatesKeyedByTaskIdentifier = [[NSMutableDictionary alloc] init];

调用get方法

1.在生成request的时候处理了监听request的属性变化;
2.参数转查询字符串;
3.生成任务安全;
4.通过AFURLSessionManagerTaskDelegate使得我们的进度可以通过block回调;
5.通过AFURLSessionManagerTaskDelegate拼接我们的服务器返回数据

这里要说一个重要的方法

- (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 {
//1、为了解决iOS8一下的一个bug,调用一个串行队列来创建dataTask
    __block NSURLSessionDataTask *dataTask = nil;
    url_session_manager_create_task_safely(^{
        //原生的方法
        //使用session来创建一个NSURLSessionDataTask对象
        dataTask = [self.session dataTaskWithRequest:request];
        
    });
    //2、为什么要给task添加代理呢?
    [self addDelegateForDataTask:dataTask uploadProgress:uploadProgressBlock downloadProgress:downloadProgressBlock completionHandler:completionHandler];

    return dataTask;
}

这里为什么要给task添加代理呢?
请求大致分三步
1、发起请求
2、请求过程
3、请求完成
第一步sessionManager完成,后两步通过delegate完成。这样的设计,减少了主类(sessionManager)的复杂度,提高了代码的维护性

//为task设置关联的delegate
- (void)setDelegate:(AFURLSessionManagerTaskDelegate *)delegate
            forTask:(NSURLSessionTask *)task
{
    //task和delegate都不能为空
    NSParameterAssert(task);
    NSParameterAssert(delegate);

    //加锁确保中间代码块是原子操作,线程安全
    [self.lock lock];
    //将delegate存入字典,以taskid作为key,说明每个task都有各自的代理
    self.mutableTaskDelegatesKeyedByTaskIdentifier[@(task.taskIdentifier)] = delegate;
    //设置两个NSProgress的变量 - uploadProgress和downloadProgress,给session task添加了两个KVO事件
    [delegate setupProgressForTask:task];
    [self addNotificationObserverForTask:task];
    [self.lock unlock];
}

这里通过添加KVO实现对任务中数据传输的过程监听,通过通知来监听整个任务执行结果

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 135,026评论 19 139
  • 写在开头: 大概回忆下,之前我们讲了AFNetworking整个网络请求的流程,包括request的拼接,sess...
    涂耀辉阅读 12,335评论 30 89
  • 我们先看一下AFNetworking.h文件都给了我们什么方法 #import <Foundation/Found...
    潇岩阅读 657评论 0 1
  • 今天复习了武志红的心理学课第一章,记录一下。 一、自我实现的预言 定义:一旦你说了一句话,你就会爱上你自己说的这句...
    一轮明月随潮涌阅读 177评论 0 1
  • 以前农村孩子考上大学是能够改变一家人的命运,随着时间推进,这种情况会越来越少见。随着教育成本增加,农村孩子以后不得...
    桃源居阅读 194评论 0 0