小白的AFNetWorking之路
淘汰掉了ASIHTTPRequest和MKNetworkit,AFNetworking完美勝出
起初
新建一個(gè)工程HelloWorld,你想在這個(gè)工程中通過pod來集成使用第三方庫AFNetworking。
使用終端進(jìn)入工程根目錄,然后編輯Podfile:
vim Podfile
【這里你也許會(huì)遇到一個(gè)問題終端左下角會(huì)提示E353:Nothing in register,不要慌,這并不是什么問題,而是自己操作錯(cuò)誤,這時(shí)候只要按【i】或者【a】進(jìn)入vi的插入模式就可以編輯了】
這里普及一下vi的工作模式:
1、命令行模式:用光標(biāo)在字符之間來回移動(dòng),進(jìn)行刪除、復(fù)制、移動(dòng)字符等操作,按【i】或者【a】進(jìn)入插入模式,按【:】(冒號(hào))進(jìn)入末行模式;
2、插入模式:輸入你要編輯的內(nèi)容,按【esc】返回命令行模式,按【:】(冒號(hào))進(jìn)入末行模式;
3、末行模式:保存文件或者退出vi,輸入【wq】存盤并退出vi,輸入【q!】不保存強(qiáng)制退出vi,輸入【w:filename】將文件保存為制定的文件名。
結(jié)束上述Podfile編輯后,在終端運(yùn)行
pod install
【 相關(guān)命令`pod repo update` or with `pod install --repo-update`】
了解
AFNetworking框架由會(huì)話(NSURLSeeion)、網(wǎng)絡(luò)監(jiān)聽模塊(Reachability)、網(wǎng)絡(luò)安全模塊(Security)、請(qǐng)求序列化(Serialization)、響應(yīng)序列化(Serialization)和UIKit集成模塊(UIKit)構(gòu)成
如圖:
庫中最核心的類是AFURLSessionManager,使用頻率最高的是其子類AFHTTPSessionManager,在該類中包含了負(fù)責(zé)請(qǐng)求序列化的AFURLRequestSerialization和響應(yīng)序列化AFURLResponseSerializer,AFURLSessionManager還提供了會(huì)話模塊NSURLSession、保證網(wǎng)絡(luò)安全的AFSecurityPolicy、網(wǎng)絡(luò)監(jiān)聽的AFNetworkReachabilityManager。
如圖:
使用
首先在頭部導(dǎo)入#import <AFNetworking/AFNetworking.h>
寫個(gè)get請(qǐng)求
// 實(shí)現(xiàn)一個(gè)get請(qǐng)求 -(void)makeGetRequest{AFHTTPSessionManager *sessionManager = [AFHTTPSessionManager manager];NSDictionary *headerDic = [NSDictionary dictionaryWithObjectsAndKeys:@"application/json",@"Content-Type", nil];[sessionManager GET:@"http://wna.test.com/app" parameters:nil headers:headerDic progress:^(NSProgress * _Nonnull downloadProgress) {} success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {NSLog(@"接口請(qǐng)求成功-- %@",responseObject);} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {NSLog(@"接口請(qǐng)求失敗-- %@",error);}]; }寫個(gè)post請(qǐng)求
// 實(shí)現(xiàn)一個(gè)post請(qǐng)求 - (void)makePostRequest{AFHTTPSessionManager *sessionManager = [AFHTTPSessionManager manager];NSDictionary *headerDic = @{@"nbp-app-name":@"dog",@"Content-Type":@"application/json",};NSDictionary *parames = @{@"methodType":@"GET",@"moduleName":@"app-product",@"url":@"product/new_product_list",};[sessionManager POST:@"http://wna.test.com/app" parameters:parames headers:headerDic progress:^(NSProgress * _Nonnull uploadProgress) {} success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {NSData *tempDisplay = [NSJSONSerialization dataWithJSONObject:responseObject options:NSJSONWritingPrettyPrinted error:nil];NSString *result = [[NSString alloc] initWithData:tempDisplay encoding:NSUTF8StringEncoding];NSLog(@"接口請(qǐng)求成功-- %@",result);} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {NSLog(@"接口請(qǐng)求失敗-- %@",error);}]; }方法的逐級(jí)調(diào)用
get方法的源碼:
- (NSURLSessionDataTask *)GET:(NSString *)URLStringparameters:(nullable id)parametersheaders:(nullable NSDictionary <NSString *, NSString *> *)headersprogress:(nullable void (^)(NSProgress * _Nonnull))downloadProgresssuccess:(nullable void (^)(NSURLSessionDataTask * _Nonnull, id _Nullable))successfailure:(nullable void (^)(NSURLSessionDataTask * _Nullable, NSError * _Nonnull))failure {NSURLSessionDataTask *dataTask = [self dataTaskWithHTTPMethod:@"GET"URLString:URLStringparameters:parametersheaders:headersuploadProgress:nildownloadProgress:downloadProgresssuccess:successfailure:failure];[dataTask resume];return dataTask; }入?yún)⒂姓?qǐng)求的URL,參數(shù),請(qǐng)求頭,進(jìn)度Block,成功Block和失敗Block。在這個(gè)方法中初始化了一個(gè)NSURLSessionDataTask的類,NSURLSessionDataTask繼承自NSURLSessionTask,NSURLSessionDataTask不提供NSURLSessionTask的任何附加功能,他的存在是為了區(qū)別于上載NSURLSessionUploadTask和下載NSURLSessionDownloadTask。
繼續(xù)往下看
- (NSURLSessionDataTask *)dataTaskWithHTTPMethod:(NSString *)methodURLString:(NSString *)URLStringparameters:(nullable id)parametersheaders:(nullable NSDictionary <NSString *, NSString *> *)headersuploadProgress:(nullable void (^)(NSProgress *uploadProgress)) uploadProgressdownloadProgress:(nullable void (^)(NSProgress *downloadProgress)) downloadProgresssuccess:(nullable void (^)(NSURLSessionDataTask *task, id _Nullable responseObject))successfailure:(nullable void (^)(NSURLSessionDataTask * _Nullable task, NSError *error))failure {NSError *serializationError = nil;NSMutableURLRequest *request = [self.requestSerializer requestWithMethod:method URLString:[[NSURL URLWithString:URLString relativeToURL:self.baseURL] absoluteString] parameters:parameters error:&serializationError];for (NSString *headerField in headers.keyEnumerator) {[request setValue:headers[headerField] forHTTPHeaderField:headerField];}if (serializationError) {if (failure) {dispatch_async(self.completionQueue ?: dispatch_get_main_queue(), ^{failure(nil, serializationError);});}return nil;}__block NSURLSessionDataTask *dataTask = nil;dataTask = [self dataTaskWithRequest:requestuploadProgress:uploadProgressdownloadProgress:downloadProgresscompletionHandler:^(NSURLResponse * __unused response, id responseObject, NSError *error) {if (error) {if (failure) {failure(dataTask, error);}} else {if (success) {success(dataTask, responseObject);}}}];return dataTask; }在這個(gè)方法的實(shí)現(xiàn)里主要做了兩個(gè)事情:
在這個(gè)方法里是通過一個(gè)實(shí)現(xiàn)了AFURLRequestSerialization協(xié)議的請(qǐng)求序列化實(shí)例對(duì)象AFHTTPRequestSerializer來調(diào)用其實(shí)例方法得到一個(gè)NSMutableURLRequest對(duì)象。
- (nullable NSMutableURLRequest *)requestWithMethod:(NSString *)methodURLString:(NSString *)URLStringparameters:(nullable id)parameterserror:(NSError * _Nullable __autoreleasing *)error;我們看下該方法的實(shí)現(xiàn)
- (NSMutableURLRequest *)requestWithMethod:(NSString *)methodURLString:(NSString *)URLStringparameters:(id)parameterserror:(NSError *__autoreleasing *)error {NSParameterAssert(method);NSParameterAssert(URLString);// 初識(shí)化URLNSURL *url = [NSURL URLWithString:URLString];NSParameterAssert(url);// 初始化RequestNSMutableURLRequest *mutableRequest = [[NSMutableURLRequest alloc] initWithURL:url];// 設(shè)置請(qǐng)求方式mutableRequest.HTTPMethod = method;// 為某些屬性賦值【allowsCellularAccess,cachePolicy,HTTPShouldHandleCookies,HTTPShouldUsePipelining,networkServiceType,timeoutInterval】for (NSString *keyPath in AFHTTPRequestSerializerObservedKeyPaths()) {if ([self.mutableObservedChangedKeyPaths containsObject:keyPath]) {[mutableRequest setValue:[self valueForKeyPath:keyPath] forKey:keyPath];}}// 調(diào)用實(shí)現(xiàn)的協(xié)議mutableRequest = [[self requestBySerializingRequest:mutableRequest withParameters:parameters error:error] mutableCopy];return mutableRequest; }在實(shí)現(xiàn)的協(xié)議中,真正的完成了一條完整的請(qǐng)求,請(qǐng)求地址,請(qǐng)求頭,請(qǐng)求體
- (NSURLRequest *)requestBySerializingRequest:(NSURLRequest *)requestwithParameters:(id)parameterserror:(NSError *__autoreleasing *)error {NSParameterAssert(request);NSMutableURLRequest *mutableRequest = [request mutableCopy];[self.HTTPRequestHeaders enumerateKeysAndObjectsUsingBlock:^(id field, id value, BOOL * __unused stop) {if (![request valueForHTTPHeaderField:field]) {// 設(shè)置請(qǐng)求頭[mutableRequest setValue:value forHTTPHeaderField:field];}}];// 序列化參數(shù) 用&拼接NSString *query = nil;if (parameters) {if (self.queryStringSerialization) {NSError *serializationError;query = self.queryStringSerialization(request, parameters, &serializationError);if (serializationError) {if (error) {*error = serializationError;}return nil;}} else {switch (self.queryStringSerializationStyle) {case AFHTTPRequestQueryStringDefaultStyle:query = AFQueryStringFromParameters(parameters);break;}}}// 如果是GET,HEAD,DELETE 走這邊if ([self.HTTPMethodsEncodingParametersInURI containsObject:[[request HTTPMethod] uppercaseString]]) {// 將序列化的參數(shù)拼到后面if (query && query.length > 0) {mutableRequest.URL = [NSURL URLWithString:[[mutableRequest.URL absoluteString] stringByAppendingFormat:mutableRequest.URL.query ? @"&%@" : @"?%@", query]];}} else {// POST、PUT走這里// #2864: an empty string is a valid x-www-form-urlencoded payloadif (!query) {query = @"";}// 如果沒有設(shè)置Content-Type,此處默認(rèn)設(shè)置成application/x-www-form-urlencodedif (![mutableRequest valueForHTTPHeaderField:@"Content-Type"]) {[mutableRequest setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"];}// 配置請(qǐng)求體[mutableRequest setHTTPBody:[query dataUsingEncoding:self.stringEncoding]];}return mutableRequest; }上面這塊是NSMutableURLRequest的整個(gè)過程,下面看下NSURLSessionDataTask
- (NSURLSessionDataTask *)dataTaskWithRequest:(NSURLRequest *)requestuploadProgress:(nullable void (^)(NSProgress *uploadProgress)) uploadProgressBlockdownloadProgress:(nullable void (^)(NSProgress *downloadProgress)) downloadProgressBlockcompletionHandler:(nullable void (^)(NSURLResponse *response, id _Nullable responseObject, NSError * _Nullable error))completionHandler {NSURLSessionDataTask *dataTask = [self.session dataTaskWithRequest:request];[self addDelegateForDataTask:dataTask uploadProgress:uploadProgressBlock downloadProgress:downloadProgressBlock completionHandler:completionHandler];return dataTask; }該方法中通過NSURLSession創(chuàng)建了一個(gè)NSURLSessionDataTask對(duì)象,并給dataTask添加代理
在session的初始化中添加了安全鎖,保證了線程的安全。
- (NSURLSession *)session {@synchronized (self) {if (!_session) {_session = [NSURLSession sessionWithConfiguration:self.sessionConfiguration delegate:self delegateQueue:self.operationQueue];}}return _session; } - (void)addDelegateForDataTask:(NSURLSessionDataTask *)dataTaskuploadProgress:(nullable void (^)(NSProgress *uploadProgress)) uploadProgressBlockdownloadProgress:(nullable void (^)(NSProgress *downloadProgress)) downloadProgressBlockcompletionHandler:(void (^)(NSURLResponse *response, id responseObject, NSError *error))completionHandler {AFURLSessionManagerTaskDelegate *delegate = [[AFURLSessionManagerTaskDelegate alloc] initWithTask:dataTask];delegate.manager = self;delegate.completionHandler = completionHandler;dataTask.taskDescription = self.taskDescriptionForSessionTasks;[self setDelegate:delegate forTask:dataTask];delegate.uploadProgressBlock = uploadProgressBlock;delegate.downloadProgressBlock = downloadProgressBlock; }上面就是一條完整的調(diào)用流程,回到最初的地方[dataTask resume];開始網(wǎng)絡(luò)請(qǐng)求
AFN使用技巧
相關(guān)面試問題:
AFURLSessionManager主要負(fù)責(zé)哪些功能?
?
?
?
?
?
?
?
總結(jié)
以上是生活随笔為你收集整理的小白的AFNetWorking之路的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 内存管理相关【内存布局内存管理方案】
- 下一篇: iOSAPP配置多环境