美文网首页
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