美文网首页
AFNetworking源码分析之NSURLSession

AFNetworking源码分析之NSURLSession

作者: hallfrita | 来源:发表于2018-10-15 17:48 被阅读0次

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

    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实现对任务中数据传输的过程监听,通过通知来监听整个任务执行结果

    相关文章

      网友评论

          本文标题:AFNetworking源码分析之NSURLSession

          本文链接:https://www.haomeiwen.com/subject/wqnfzftx.html