1、首先我们简单的写个get请求:js view plain copy print?AFHTTPSessionManager *manager = AFHTTPSessionManager allocinit; manager GET:http:/localhost parameters:nil progress:nil success:(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) failure:(NSURLSessionDataTask * _Nullable task, NSError * _Nonnu
2、ll error) ;首先我们我们调用了初始化方法生成了一个manager,我们点进去看看初始化做了什么:- (instancetype)init return self initWithBaseURL:nil; - (instancetype)initWithBaseURL:(NSURL *)url url sessionConfiguration:- (instancetype)initWithSessionConfiguration:(NSURLSessionConfiguration *)configuration nil sessionConfiguration:configurat
3、ion;(NSURL *)url sessionConfiguration:(NSURLSessionConfiguration *)configuration self = super initWithSessionConfiguration: if (!self) return nil; /对传过来的BaseUrl进行处理,截去url最后的/ if (url path length 0 & !url absoluteString hasSuffix:/) url = url URLByAppendingPathComponent:; self.baseURL = url; self.req
4、uestSerializer = AFHTTPRequestSerializer serializer; self.responseSerializer = AFJSONResponseSerializer serializer; return self;初始化都调用到- (instancetype)initWithBaseURL:(NSURL *)url sessionConfiguration:(NSURLSessionConfiguration *)configuration方法中来了。其实初始化方法都调用父类的初始化方法。父类也就是AF3.x最最核心的类AFHTTPSessionMan
5、ager。几乎所有的类都是围绕着这个类在处理业务逻辑。除此之外,方法中把baseURL存了起来,还生成了一个请求序列对象和一个响应序列对象。后面再细说这两个类是干什么用的。直接来到父类AFURLSessionManager的初始化方法: return self initWithSessionConfiguration: self = super init;configuration) configuration = NSURLSessionConfiguration defaultSessionConfiguration; self.sessionConfiguration = configu
6、ration; self.operationQueue = NSOperationQueue alloc init; /queue并发线程数设置为1 self.operationQueue.maxConcurrentOperationCount = 1; /注意代理,代理的继承,实际上NSURLSession去判断了,你实现了哪个方法会去调用,包括子代理的方法! self.session = NSURLSession sessionWithConfiguration:self.sessionConfiguration delegate:self delegateQueue:self.opera
7、tionQueue; /各种响应转码 /设置默认安全策略 self.securityPolicy = AFSecurityPolicy defaultPolicy;#if !TARGET_OS_WATCH self.reachabilityManager = AFNetworkReachabilityManager sharedManager;#endif / 设置存储NSURL task与AFURLSessionManagerTaskDelegate的词典(重点,在AFNet中,每一个task都会被匹配一个AFURLSessionManagerTaskDelegate 来做task的dele
8、gate事件处理) = self.mutableTaskDelegatesKeyedByTaskIdentifier = NSMutableDictionary alloc init; / 设置AFURLSessionManagerTaskDelegate 词典的锁,确保词典在多线程访问时的线程安全 self.lock = NSLock alloc init; self.lock.name = AFURLSessionManagerLockName; / 置空task关联的代理 self.session getTasksWithCompletionHandler:(NSArray *dataT
9、asks, NSArray *uploadTasks, NSArray *downloadTasks) for (NSURLSessionDataTask *task in dataTasks) self addDelegateForDataTask:task uploadProgress:nil downloadProgress:nil completionHandler: for (NSURLSessionUploadTask *uploadTask in uploadTasks) self addDelegateForUploadTask:uploadTask progress: for
10、 (NSURLSessionDownloadTask *downloadTask in downloadTasks) self addDelegateForDownloadTask:downloadTask progress:nil destination: ;这个就是最终的初始化方法了,注释应该写的很清楚,唯一需要说的就是三点:self.operationQueue.maxConcurrentOperationCount = 1;这个operationQueue就是我们代理回调的queue。这里把代理回调的线程并发数设置为1了。至于这里为什么要这么做,我们先留一个坑,等我们讲完AF2.x之后
11、再来分析这一块。第二就是我们初始化了一些属性,其中包括self.mutableTaskDelegatesKeyedByTaskIdentifier,这个是用来让每一个请求task和我们自定义的AF代理来建立映射用的,其实AF对task的代理进行了一个封装,并且转发代理到AF自定义的代理,这是AF比较重要的一部分,接下来我们会具体讲这一块。第三就是下面这个方法:self.session getTasksWithCompletionHandler:首先说说这个方法是干什么用的:这个方法用来异步的获取当前session的所有未完成的task。其实讲道理来说在初始化中调用这个方法应该里面一个task都
12、不会有。我们打断点去看,也确实如此,里面的数组都是空的。但是想想也知道,AF大神不会把一段没用的代码放在这吧。所以我大胆猜测,可能是当我们重复去初始化session的时候(当然我们实际也不会这么做),会有新的session指向旧的有未完成task的session。为了排除这种不确定性因素,所以在初始化的时候把里面绑定的代理之类的东西都置为nil了。或许这就是防御性编程思想的一种体现吧。初始化方法到这就全部完成了。3.jpg分割图.png接着我们来看看网络请求:- (NSURLSessionDataTask *)GET:(NSString *)URLString (id)parameters p
13、rogress:(void ()(NSProgress * _Nonnull)downloadProgress success:(void ()(NSURLSessionDataTask * _Nonnull, id _Nullable)success failure:(void ()(NSURLSessionDataTask * _Nullable, NSError * _Nonnull)failure /生成一个task NSURLSessionDataTask *dataTask = self dataTaskWithHTTPMethod:GET URLString:URLString
14、parameters uploadProgress:nil downloadProgress:downloadProgress success failure; /开始网络请求 dataTask resume; return dataTask;方法走到类AFHTTPSessionManager中来,调用父类,也就是我们整个AF3.x的核心类AFURLSessionManager的方法,生成了一个系统的NSURLSessionDataTask实例,并且开始网络请求。我们继续往父类里看,看看这个方法到底做了什么:- (NSURLSessionDataTask *)dataTaskWithHTTPM
15、ethod:(NSString *)method (nullable void ()(NSProgress *uploadProgress) uploadProgress (nullable void ()(NSProgress *downloadProgress) downloadProgress (void ()(NSURLSessionDataTask *, id)success (void ()(NSURLSessionDataTask *, NSError *)failure NSError *serializationError = nil; /把参数,还有各种东西转化为一个req
16、uest NSMutableURLRequest *request = self.requestSerializer requestWithMethod:method URLString:NSURL URLWithString:URLString relativeToURL:self.baseURL absoluteString parameters:parameters error:serializationError; if (serializationError) if (failure) #pragma clang diagnostic push #pragma clang diagn
17、ostic ignored -Wgnu /如果解析错误,直接返回 dispatch_async(pletionQueue ?: dispatch_get_main_queue(), failure(nil, serializationError); );#pragma clang diagnostic pop _block NSURLSessionDataTask *dataTask = nil; dataTask = self dataTaskWithRequest:request uploadProgress completionHandler:(NSURLResponse * _unus
18、ed response, id responseObject, NSError *error) if (error) failure(dataTask, error); else if (success) success(dataTask, responseObject);这个方法做了两件事: 1.用self.requestSerializer和各种参数去获取了一个我们最终请求网络需要的NSMutableURLRequest实例。 2.调用另外一个方法dataTaskWithRequest去拿到我们最终需要的NSURLSessionDataTask实例,并且在完成的回调里,调用我们传过来的成功
19、和失败的回调。注意下面这个方法,我们常用来 push pop搭配,来忽略一些编译器的警告:这里是用来忽略:?带来的警告,具体的各种编译器警告描述,可以参考这篇:各种编译器的警告。说到底这个方法还是没有做实事,我们继续到requestSerializer方法里去看,看看AF到底如何拼接成我们需要的request的:接着我们跑到AFURLRequestSerialization类中:- (NSMutableURLRequest *)requestWithMethod: error:(NSError *_autoreleasing *)error /断言,debug模式下,如果缺少改参数,crash
20、 NSParameterAssert(method); NSParameterAssert(URLString); NSURL *url = NSURL URLWithString:URLString; NSParameterAssert(url); NSMutableURLRequest *mutableRequest = NSMutableURLRequest alloc initWithURL:url; mutableRequest.HTTPMethod = method; /将request的各种属性循环遍历 for (NSString *keyPath in AFHTTPReques
21、tSerializerObservedKeyPaths() /如果自己观察到的发生变化的属性,在这些方法里 if (self.mutableObservedChangedKeyPaths containsObject:keyPath) /把给自己设置的属性给request设置 mutableRequest setValue:self valueForKeyPath:keyPath forKey:keyPath; /将传入的parameters进行编码,并添加到request中 mutableRequest = self requestBySerializingRequest:mutableRe
22、quest withParameters:error mutableCopy; return mutableRequest;讲一下这个方法,这个方法做了3件事:1)设置request的请求类型,get,post,put.等2)往request里添加一些参数设置,其中AFHTTPRequestSerializerObservedKeyPaths()是一个c函数,返回一个数组,我们来看看这个函数:static NSArray * AFHTTPRequestSerializerObservedKeyPaths() static NSArray *_AFHTTPRequestSerializerObs
23、ervedKeyPaths = nil; static dispatch_once_t onceToken; / 此处需要observer的keypath为allowsCellularAccess、cachePolicy、HTTPShouldHandleCookies / HTTPShouldUsePipelining、networkServiceType、timeoutInterval dispatch_once(&onceToken, _AFHTTPRequestSerializerObservedKeyPaths = NSStringFromSelector(selector(allow
24、sCellularAccess), NSStringFromSelector(selector(cachePolicy), NSStringFromSelector(selector(HTTPShouldHandleCookies), NSStringFromSelector(selector(HTTPShouldUsePipelining), NSStringFromSelector(selector(networkServiceType), NSStringFromSelector(selector(timeoutInterval); /就是一个数组里装了很多方法的名字, return _AFHTTPRequestSerializerO
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1