通過前面學習的HTTP協議的基本知識,GET/POST請求的區別,NSURLConnection 和 NSURLSession的使用,已經基本了解了網絡請求的方法,但是相對使用比較麻煩,AFNetworking是對NSURLConnection 和 NSURLSession的封裝,使網絡請求更加簡單輕松,是一款非常有用的第三方框架。AFNetworking3.0以后移除了對NSURLConnection的支持。 看一下AFNetworking 歷史版本 以及框架
AFNetworking版本更新
AFNetworking框架
這些在GitHub上都可以看到,可以去GitHub上查看。
AFHTTPSessionManager *manager =[AFHTTPSessionManager manager]; NSDictionary *dict = @{ @"username":@"520it", @"pwd":@"520it" }; // parameters 參數字典 [manager GET:@"http://120.25.226.186:32812/login" parameters:dict progress:^(NSProgress * _Nonnull downloadProgress) { //進度 //進度 } success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseobject) { // task 我們可以通過task拿到響應頭 // responseObject:請求成功返回的響應結果(AFN內部已經把響應體轉換為OC對象,通常是字典或數組) } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) { // error 錯誤信息 }];
AFHTTPSessionManager *manager =[AFHTTPSessionManager manager]; NSDictionary *dict = @{ @"username":@"520it", @"pwd":@"520it" }; [manager POST:@"http://120.25.226.186:32812/login" parameters:dict progress:^(NSProgress * _Nonnull downloadProgress) { // 進度 } success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) { // 請求成功 } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) { // 請求失敗 }];
注意:我們發現GET和POST請求一模一樣,僅僅換了一個名字,GET請求也可以將參數放在字典中,也可以將參數拼接在url之后parameters傳nil。另外不需要開啟Task,因為AFN內部已經幫我們開啟了 另外:AFN默認會把服務器返回給我們的數據當做是JSNO數據,并且AFN內部已經把響應體JSON數據轉換為OC對象,通常是字典或數組。 那么如果服務器返回的XML呢?這時我們需要自己設置AFN解析方式
manager.responseSerializer = [AFXMLParserResponseSerializer serializer];
返回的是NSXMLParser,需要我們自己解析
如果返回的數據既不是JSON也不是XML那么需要設置
manager.responseSerializer = [AFHTTPResponseSerializer serializer];
AFN默認接收的ContentTypes 有以下三種
ContentType
如果服務器返回的ContentType不是這三種中的一種,我們就需要設置
manager.responseSerializer.acceptableContentTypes = [NSSet setWithObject:@"text/html"];
也可以直接在AFN源碼中添加(不建議使用,這種方式比較隱蔽,當更新過AFN之后這里會還原,出現問題比較難找)
直接添加即可
// 1.創建一個管理者 AFHTTPSessionManager *manager = [AFHTTPSessionManager manager]; // 2. 創建請求對象 NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/resources/images/minion_03.png"]; NSURLRequest *request =[NSURLRequest requestWithURL:url]; // 3. 下載文件 NSURLSessionDownloadTask *downloadTask = [manager downloadTaskWithRequest:request progress:^(NSProgress * _Nonnull downloadProgress) { // downloadProgress.completedUnitCount 當前下載大小 // downloadProgress.totalUnitCount 總大小 NSLog(@"%f", 1.0 * downloadProgress.completedUnitCount / downloadProgress.totalUnitCount); } destination:^NSURL * _Nonnull(NSURL * _Nonnull targetPath, NSURLResponse * _Nonnull response) { // targetPath 臨時存儲地址 NSLog(@"targetPath:%@",targetPath); NSString *path =[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject]; NSString *filePath = [path stringByAppendingPathComponent:response.suggestedFilename]; NSURL *url = [NSURL fileURLWithPath:filePath]; NSLog(@"path:%@",filePath); // 返回url 我們想要存儲的地址 // response 響應頭 return url; } completionHandler:^(NSURLResponse * _Nonnull response, NSURL * _Nullable filePath, NSError * _Nullable error) { // 下載完成之后調用 // response 響應頭 // filePath 下載存儲地址 NSLog(@"filePath:%@",filePath); }]; // 需要手動開啟 [downloadTask resume];
注意: 1. 下載文件需要獲取NSURLSessionDownloadTask對象手動開啟 2. 第一個block塊:downloadProgress 有兩個屬性completedUnitCount(已經下載文件大小)、totalUnitCount(文件總大小)。 3. 第二個block塊:需要返回一個url,表示想要將文件存儲的地方。targetPath:表示臨時存儲地址在tmp臨時文件中。response:響應頭 可以拿到一些文件信息 4. 第三個block塊:下載完成之后調用。response:響應頭。filePath:文件存儲地址,與第二個block塊中返回的url是一個地址
關于文件上傳使用AFN就簡單多了,也不需要我們去拼接請求體和請求文件參數啦,AFN內部已經幫我們拼接好了 方法一:formData 添加data形式數據
AFHTTPSessionManager *manager = [AFHTTPSessionManager manager]; NSString *url =@"http://120.25.226.186:32812/upload"; [manager POST:url parameters:nil constructingBodyWithBlock:^(id<AFMultipartFormData> _Nonnull formData) { // formData 將要上傳的數據 UIImage *image =[UIImage imageNamed:@"123"]; NSData *data =UIImagePNGRepresentation(image); // 方法一 /** data:上傳文件二進制數據 name:接口的名字 fileName:文件上傳到服務器之后叫什么名字 mineType:上傳文件的類型,可以上傳任意二進制mineType. */ [formData appendPartWithFileData:data name:@"file" fileName:@"123.png" mimeType:@"image/png"]; // 方法二 /** data:上傳文件二進制數據 name:接口的名字 這種方法內部會將文件名當做上傳到服務器之后的名字,并自動獲取其類型 */ [formData appendPartWithFormData:data name:@"file"]; } progress:^(NSProgress * _Nonnull uploadProgress) { // 上傳進度 } success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) { // 上傳成功 NSLog(@"上傳成功"); } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) { // 上傳失敗 NSLog(@"上傳失敗"); }];
方法二:formData直接添加url
AFHTTPSessionManager *manager = [AFHTTPSessionManager manager]; NSString *url =@"http://120.25.226.186:32812/upload"; [manager POST:url parameters:nil constructingBodyWithBlock:^(id<AFMultipartFormData> _Nonnull formData) { // formData 將要上傳的數據 // 直接傳URL NSURL *url =[NSURL fileURLWithPath:@"/Users/yangboxing/Desktop/Snip20160905_7.png"]; // 方法一 [formData appendPartWithFileURL:url name:@"file" fileName:@"hhaha.png" mimeType:@"image/png" error:nil]; // 方法二 /** 這個方法會自動截取url最后一塊的文件名作為上傳到服務器的文件名 也會自動獲取mimeType,如果沒有辦法獲取mimeType 就使用@"application/octet-stream" 表示任意的二進制數據 ,當我們不在意文件類型的時候 也可以用這個。 */ [formData appendPartWithFileURL:url name:@"file" error:nil]; } progress:^(NSProgress * _Nonnull uploadProgress) { // 上傳進度 } success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) { // 上傳成功 NSLog(@"上傳成功"); } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) { // 上傳失敗 NSLog(@"上傳失敗"); }];
注意: mimeType表示文件的類型,關于mimeType類型可以自行百度,我們也可以通過發送請求獲取mineType
// 通過發送請求獲取mimeType-(NSString *)connectSync:(NSString *)path{ //1.確定請求路徑 NSURL *url = [NSURL fileURLWithPath:path]; //2.創建可變的請求對象 NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; NSHTTPURLResponse *res = nil; [NSURLConnection sendSynchronousRequest:request returningResponse:&res error:nil]; NSLog(@"%@",res.MIMEType); return res.MIMEType;}
我們通過[formData appendPartWithFileURL:url name:@"file" error:nil];
來看看AFN是如何獲取mimeType的
文件名稱和mimeType獲取
進入方法內部
mimeType獲取
因此以后我們要獲取mimeType的時候也可以直接從AFN中復制拿去用嘍。
使用AFN進行網絡狀態的檢測非常簡單,并且可以持續監聽網絡狀態,每當網絡狀態發生改變的時候,都會調用setReachabilityStatusChangeBlock方法
AFNetworkReachabilityManager *manager = [AFNetworkReachabilityManager sharedManager]; /* AFNetworkReachabilityStatusUnknown = -1, 未知 AFNetworkReachabilityStatusNotReachable = 0, 沒有網絡 AFNetworkReachabilityStatusReachableViaWWAN = 1, 蜂窩流量 AFNetworkReachabilityStatusReachableViaWiFi = 2, 無線 */ // 監聽網絡狀態的變化 [manager setReachabilityStatusChangeBlock:^(AFNetworkReachabilityStatus status) { switch (status) { case AFNetworkReachabilityStatusUnknown: NSLog(@"未知"); break; case AFNetworkReachabilityStatusNotReachable: NSLog(@"沒有網絡"); break; case AFNetworkReachabilityStatusReachableViaWWAN: NSLog(@"3G"); break; case AFNetworkReachabilityStatusReachableViaWiFi: NSLog(@"無線"); break; default: break; } }]; // 開啟 [manager startMonitoring];
我們知道HTTPS在HTTP的基礎上加入了SSL協議,SSL依靠證書來驗證服務器的身份,并為瀏覽器和服務器之間的通信加密。 當使用NSURLSession來向HTTPS發送請求時,需要在NSURLSessionDataDelegate
的代理方法didReceiveChallenge
中,信任服務器并且創建證書返回服務器。 而AFN對此進行了很好的封裝,內部已經幫我們做好這些,因此向HTTPS發送請求方法與向HTTP發送請求是一樣的。 我們來看AFN內部封裝的方法
AFN內部封裝的方法
那么當我們用NSURLSession向HTTPS發送請求的時候,直接復制過來稍作修改就可以用啦
-(void)URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition, NSURLCredential * _Nullable))completionHandler{ NSLog(@"--didReceiveChallenge--%@",challenge.protectionSpace); /* NSURLSessionAuthChallengeUseCredential = 0, 使用 NSURLSessionAuthChallengePerformDefaultHandling = 1, 忽略(默認) NSURLSessionAuthChallengeCancelAuthenticationChallenge = 2,忽略(會取消請求) NSURLSessionAuthChallengeRejectProtectionSpace = 3, 忽略(下次繼續詢問) */ // NSURLAuthenticationMethodServerTrust 服務器信任 if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) { //創建證書 NSURLCredential *credentoal = [[NSURLCredential alloc]initWithTrust:challenge.protectionSpace.serverTrust]; completionHandler(NSURLSessionAuthChallengeUseCredential,credentoal); }}
我們一般在使用AFN的時候會將他封裝到一個工具類中,使工具類成為一個中間層,這樣便于我們使用和對代碼的管理,以后當AFN更新或者我們要換網絡請求第三方類庫的時候,直接更改工具類就可以了,其他類中的的網絡請求方法都不用改變,這使我們以后維護代碼更加簡單快捷方便。
關于網絡請求的基礎知識請參考iOS-網絡編程(一)HTTP協議、iOS-網絡編程(二)文件上傳和斷點離線下載。
?本文借鑒了很多前輩的文章,如果有不對的地方請指正,歡迎大家一起交流學習 xx_cc 。
本文由 貴州做網站公司 整理發布,部分圖文來源于互聯網,如有侵權,請聯系我們刪除,謝謝!
網絡推廣與網站優化公司(網絡優化與推廣專家)作為數字營銷領域的核心服務提供方,其價值在于通過技術手段與策略規劃幫助企業提升線上曝光度、用戶轉化率及品牌影響力。這...
在當今數字化時代,公司網站已成為企業展示形象、傳遞信息和開展業務的重要平臺。然而,對于許多公司來說,網站建設的價格是一個關鍵考量因素。本文將圍繞“公司網站建設價...
在當今的數字化時代,企業網站已成為企業展示形象、吸引客戶和開展業務的重要平臺。然而,對于許多中小企業來說,高昂的網站建設費用可能會成為其發展的瓶頸。幸運的是,隨...
c230series 芯片組參數?英特爾Skylake-S-100系列/C230系列芯片組其實就是英特爾H110芯片組的主板,1151針,六代平臺的主板可以支持i7 6700K CPU,但是主板不支持超頻。I7 6700K CPU建議配Z170或Z270主板,支持超頻。c230芯片是什么主板?服務器C230芯片組,E3 1230V5專用主板芯片組,目前E3主板是華碩E3 PRO gaming V5...
正能量的歌一直深得人心汪峰-《英雄》北京國安球隊隊歌,聽見這首歌情況下你是不是覺得心潮澎湃?是不是有一種想要去開辟大場面的想法?也許和平時期獲得一場比賽也是英雄。國安隊歌歌詞誰知道???漢化版綠茵場上叫喊著姓名 翠綠色影子也是我們的大牌明星 向著未來 噢 朝著全球 去拼搏大家憧憬的殊榮 獲勝始終屬于你 北京國安永遠爭第一 喔噢…… 北京國安 我們永遠支持你 噢…… 北京國安 大家永遠熱愛你 綠茵場上...
國內有哪些股票跟巴菲特的投資理念相似?石油,比亞迪,巴菲特都買過巴菲特的股票,但是他沒動。為什么他在股市大跌的時候買了港股中石油,然后大漲之后又賣了?巴菲特概念是什么意思?概念股指數巴菲特根據自己的計算和推測購買的股票。雖然短期內收益無法顯現,但長期來看是有效的。巴菲特對比亞迪的投資似乎打破了他的第一條投資戒律:永遠不要投資你不了解其業務的公司。即使從1999年到2000年,網絡泡沫最嚴重的時候,...