iOSAFNetworking 網絡請求

  • 在 iOS 開發中,通常狀況下,簡單的向某個 Web 站點簡單的頁面提交請求並獲取服務器的響應,用 Xcode 自帶的 NSURLConnection 是能勝任的。可是,在絕大部分下咱們所須要訪問的 Web 頁面則是屬於那種受到權限保護的頁面,並非有一個簡單的 URL 能夠訪問的。這就涉及到了 Session 和 Cookie 的處理了,在此時使用 NSURLConnection 也是可以達到要求的,只是其中處理起來的複雜度和難度就提高了。爲了更好的處理向 Web 站點的請求,包括處理 Session,Cookie 等細節問題,使用 AFNetworking 則是更好的選擇。php

    • 1) Session:中文有譯做時域的,就是指某個客戶端從訪問服務器起到中止訪問這一段的時間間隔被稱爲時域。
    • 2) Cookie:由服務器發送給客戶端,把 Cookie 的 key:value 值儲存在本地文件夾下,當下次請求的時候可以直接發送 Cookie 得到權限驗證。

一、AFNetworking

1.1 AFNetworking 特色

  • AFNetworking 是一個討人喜歡的網絡庫,適用於 iOS,Mac OS X 以及 Watch OS。
  • AFNetworking 構建在 NSURLSession,NSOperation,以及其餘熟悉的 Foundation 技術之上。它擁有良好的架構,豐富的 API,以及模塊化構建方式,使得使用起來很是輕鬆。
  • AFNetworking 能夠用於發送 HTTP 請求,接收 HTTP 的響應,可是不會緩存服務器的響應,不能執行 HTML 頁面中的 JAvascript 代碼。
  • AFNetworking 內置支持 JSON,Plist 文件和 XML 文件的半自動序列化和反序列化,能夠對 JSON 格式的請求響應數據自動作反序列化,XML 格式數據須要手動反序列化,使用比較方便。
  • AFNetworking 中回調函數將在主線程中進行,程序員不須要關心線程間通信問題。
  • AFNetworking 具備完善的錯誤處理機制。

1.2 AFNetworking 官方使用建議

  • 創建 AFHTTPSesssionManager 的單例子類,統一管理全局的全部網絡訪問。html

    • NetworkTools.hjava

      #import <AFNetworking/AFNetworking.h> @interface NetworkTools : AFHTTPSessionManager + (instancetype)sharedNetworkTools; @end
    • NetworkTools.mgit

      @implementation NetworkTools + (instancetype)sharedNetworkTools { static NetworkTools *tools; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ // baseURL 的目的,就是讓後續的網絡訪問直接使用 相對路徑便可,baseURL 的路徑必定要有 / 結尾 NSURL *baseURL = [NSURL URLWithString:@"http://c.m.163.com/"]; NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration]; tools = [[self alloc] initWithBaseURL:baseURL sessionConfiguration:config]; // 修改 解析數據格式 可以接受的內容類型 - 官方推薦的作法,民間作法:直接修改 AFN 的源代碼 tools.responseSerializer.acceptableContentTypes = [NSSet setWithObjects:@"application/json", @"text/json", @"text/javascript", @"text/html", nil]; }); return tools; } @end

1.3 AFNetworking 系統需求

AFNetworking Version Minimum iOS Target Target Notes
3.x iOS 7 Xcode 7+ is required. NSURLConnectionOperation support has been removed.
2.6 -> 2.6.3 iOS 7 Xcode 7+ is required.
2.0 -> 2.5.4 iOS 6 Xcode 5+ is required. NSURLSession subspec requires iOS 7 or OS X 10.9.
1.x iOS 5  
0.10.x iOS 4  

1.4 AFNetworking 框架結構

  • 1) V 2.5.4:程序員

    NSURLConnection 對 NSURLConnection 網絡請求的封裝(iOS 9.0 DEPRECATED) AFURLConnectionOperation AFHTTPRequestOperation AFHTTPRequestOperationManager NSURLSession 對 NSURLSession 網絡請求的封裝(iOS 7.0 AVAILABLE) AFURLSessionManager AFHTTPSessionManager Serialization 序列化 & 反序列化 格式 <AFURLRequestSerialization> 發送給服務器的數據格式(序列化) AFHTTPRequestSerializer 二進制 默認 AFJSONRequestSerializer JSON POST JSON AFPropertyListRequestSerializer Plist 蘋果專有,極少用 <AFURLResponseSerialization> 從服務器接收的數據格式(反序列化) AFHTTPResponseSerializer 二進制 AFJSONResponseSerializer JSON 默認 AFXMLParserResponseSerializer XMLParser SAX 解析 AFXMLDocumentResponseSerializer (Mac OS X) XMLDocument DOM 解析 AFPropertyListResponseSerializer Plist 蘋果專有,極少用 AFImageResponseSerializer Image 圖片 AFCompoundResponseSerializer Compound 組合的 Additional Functionality 輔助功能 AFSecurityPolicy 安全策略 AFNetworkReachabilityManager 網絡狀態監測 UIKit+AFNetworking AFNetworking 爲相應的 UIKit 控件添加的分類。
  • 2) V 3.1.0:github

    NSURLSession 對 NSURLSession 網絡請求的封裝(iOS 7.0 AVAILABLE) AFURLSessionManager AFHTTPSessionManager Serialization 序列化 & 反序列化 格式 <AFURLRequestSerialization> 發送給服務器的數據格式(序列化) AFHTTPRequestSerializer 二進制 默認 AFJSONRequestSerializer JSON POST JSON AFPropertyListRequestSerializer Plist 蘋果專有,極少用 <AFURLResponseSerialization> 從服務器接收的數據格式(反序列化) AFHTTPResponseSerializer 二進制 AFJSONResponseSerializer JSON 默認 AFXMLParserResponseSerializer XMLParser SAX 解析 AFXMLDocumentResponseSerializer (Mac OS X) XMLDocument DOM 解析 AFPropertyListResponseSerializer Plist 蘋果專有,極少用 AFImageResponseSerializer Image 圖片 AFCompoundResponseSerializer Compound 組合的 Additional Functionality 輔助功能 AFSecurityPolicy 安全策略 AFNetworkReachabilityManager 網絡狀態監測 UIKit+AFNetworking AFNetworking 爲相應的 UIKit 控件添加的分類。
  • 3)NSURLConnection 網絡請求封裝:json

    iOS 9.0 DEPRECATED 1> AFHTTPRequestOperationManager: 屬性: requestSerializer :設置請求的數據格式 responseSerializer :設置響應的數據格式 reachabilityManager :網絡鏈接狀態管理器,監控網絡鏈接狀態 方法: HTTPRequestOperationWithRequest:若是須要在請求中設置額外的屬性,例如:身份驗證,提早準備好 request ,調用此方法就能夠了 manager :實例化 HTTP Reuqest 管理器 GET :GET 請求 HEAD :HEAD 請求 POST :POST 請求,constructingBodyWithBlock:POST 上傳文件用的 PUT :PUT 請求 PATCH :PATCH 請求,RESTFul 的一個方法,極少用 DELETE :DELETE 請求 全部的方法:參數字典 成功回調 失敗回調 URL 都是使用字符串來傳遞的
  • 4) NSURLSession 網絡請求封裝:瀏覽器

    iOS 7.0 AVAILABLE 1> 說明: 基於指定的 NSURLSessionConfiguration 建立並管理一個 NSURLSession 對象。 遵照 NSURLSessionTaskDelegate、NSURLSessionDataDelegate、NSURLSessionDownloadDelegate 和 NSURLSessionDelegate 協議。 2> 初始化: 初始化 :- (instancetype)initWithSessionConfiguration:(NSURLSessionConfiguration *)configuration 取消 :- (void)invalidateSessionCancelingTasks:(BOOL)cancelPendingTasks; 3> 任務: 數據任務:dataTaskWithRequest: 上傳任務: 從文件上傳 :uploadTaskWithRequest:fromFile: 從數據上傳 :uploadTaskWithRequest:fromData: 從數據流上傳 :uploadTaskWithStreamedRequest: 下載任務: 使用指定的請求建立下載任務 :downloadTaskWithRequest: 使用續傳數據建立下載任務 :downloadTaskWithResumeData: 任務進度: 上傳進度:- (NSProgress *)uploadProgressForTask:(NSURLSessionUploadTask *)uploadTask; 下載進度:- (NSProgress *)downloadProgressForTask:(NSURLSessionDownloadTask *)downloadTask; 4> 代理回調: <1> 會話代理回調: 設置管理的會話無效回調方法: - (void)setSessionDidBecomeInvalidBlock:(void (^)(NSURLSession *session, NSError *error))block; block 參數: session :會話 error :致使會話無效相關的錯誤 設置當管理的會話無效時執行的 block。 設置須要身份驗證回調方法: - (void)setSessionDidReceiveAuthenticationChallengeBlock: (NSURLSessionAuthChallengeDisposition (^)(NSURLSession *session, NSURLAuthenticationChallenge *challenge, NSURLCredential * __autoreleasing *credential))block; block 參數: session :會話 challenge :身份驗證質詢 credential :指向憑據的指針,該憑據用於解決身份驗證 block 返回值: 返回身份驗證的配置狀況 設置當鏈接須要身份驗證質詢時執行的 block。 <2> 任務代理回調: 設置上傳流回調方法: - (void)setTaskNeedNewBodyStreamBlock:(NSInputStream * (^)(NSURLSession *session, NSURLSessionTask *task))block; block 返回值: 要上傳文件的 NSInputStream。 設置一個請求體二進制流發送至遠程服務器時執行的 block。 設置重定向回調方法: - (void)setTaskWillPerformHTTPRedirectionBlock:(NSURLRequest * (^)(NSURLSession *session, NSURLSessionTask *task, NSURLResponse *response, NSURLRequest *request))block; block 參數: session :會話 task :任務 response :重定向響應 request :要重定向的請求 block 返回值: 返回致使重定向的請求 NSURLRequest 設置 HTTP 請求嘗試重定向到其餘 URL 時執行的 block。 設置身份驗證質詢回調方法: - (void)setTaskDidReceiveAuthenticationChallengeBlock: (NSURLSessionAuthChallengeDisposition (^)(NSURLSession *session, NSURLSessionTask *task, NSURLAuthenticationChallenge *challenge, NSURLCredential * __autoreleasing *credential))block; block 參數: session :會話 task :任務 challenge :身份驗證質詢 credential :指向解決驗證須要使用憑據的指針 block 返回值: 返回對身份驗證請求質詢的處置 設置接收到特定身份驗證質詢時執行的 block。 設置上傳進度回調方法: - (void)setTaskDidSendBodyDataBlock:(void (^)(NSURLSession *session, NSURLSessionTask *task, int64_t bytesSent, int64_t totalBytesSent, int64_t totalBytesExpectedToSend))block; block 參數: session :會話 task :任務 bytesSent :本次上傳字節數 totalBytesSent :已經上傳的字節數 totalBytesExpectedToSend :總字節數 設置跟蹤上傳進度要執行的 block。 設置任務完成回調方法: - (void)setTaskDidCompleteBlock:(void (^)(NSURLSession *session, NSURLSessionTask *task, NSError *error))block; block 參數: session :會話 task :任務 error :任務執行過程當中出現的錯誤 設置特定任務完成後執行的 block。 <3> 數據任務代理回調: 設置接收到響應回調方法: - (void)setDataTaskDidReceiveResponseBlock:(NSURLSessionResponseDisposition (^)(NSURLSession *session, NSURLSessionDataTask *dataTask, NSURLResponse *response))block; block 參數: session :會話 dataTask :任務 response :接收到的響應 block 返回值: 返回對會話響應的處置 設置數據任務接收到響應時執行的 block。 設置成爲下載任務回調方法: - (void)setDataTaskDidBecomeDownloadTaskBlock:(void (^)(NSURLSession *session, NSURLSessionDataTask *dataTask, NSURLSessionDownloadTask *downloadTask))block; block 參數: session :會話 dataTask :任務 downloadTask :成爲的下載任務 設置數據任務成爲下載任務時執行的 block。 設置接收到數據回調方法: - (void)setDataTaskDidReceiveDataBlock:(void (^)(NSURLSession *session, NSURLSessionDataTask *dataTask, NSData *data))block; block 參數: session :會話 dataTask :任務 data :接收的數據 設置數據任務接收到數據時執行的 block。 設置緩存行爲回調方法: - (void)setDataTaskWillCacheResponseBlock:(NSCachedURLResponse * (^)(NSURLSession *session, NSURLSessionDataTask *dataTask, NSCachedURLResponse *proposedResponse))block; block 參數: session :會話 dataTask :任務 proposedResponse :建議緩存的 URL 響應 block 返回值: 返回要緩存的響應 設置肯定數據任務的緩存行爲執行的 block。 設置入隊消息提交回調方法: - (void)setDidFinishEventsForBackgroundURLSessionBlock:(void (^)(NSURLSession *session))block; block 參數: session:會話 設置會話的全部入隊消息已經被提交時執行一次的 block。 <4> 下載任務代理回調: 設置下載完成回調方法: - (void)setDownloadTaskDidFinishDownloadingBlock:(NSURL * (^)(NSURLSession *session, NSURLSessionDownloadTask *downloadTask, NSURL *location))block; block 參數: session :會話 downloadTask :下載任務 location :保存下載文件的臨時位置 block 返回值: 下載文件被移動到的 URL 設置下載任務完成後執行的 block。 設置下載進度回調方法: - (void)setDownloadTaskDidWriteDataBlock:(void (^)(NSURLSession *session, NSURLSessionDownloadTask *downloadTask, int64_t bytesWritten, int64_t totalBytesWritten, int64_t totalBytesExpectedToWrite))block; block 參數: session :會話 downloadTask :下載任務 bytesWritten :本次下載字節數 totalBytesWritten :已經下載的字節數 totalBytesExpectedToWrite :總下載字節數 設置跟蹤下載進度重複執行的 block,該 block 可能會被調用屢次,並在會話管理器操做隊列中執行。 設置下載續傳回調方法: - (void)setDownloadTaskDidResumeBlock:(void (^)(NSURLSession *session, NSURLSessionDownloadTask *downloadTask, int64_t fileOffset, int64_t expectedTotalBytes))block; block 參數: session :會話 downloadTask :下載任務 fileOffset :續傳下載的文件偏移位置 expectedTotalBytes :總下載字節數 設置下載任務續傳時執行的 blok。 5> 通知: <1> 通知: AFNetworkingTaskDidResumeNotification :任務繼續通知 AFNetworkingTaskDidCompleteNotification :任務結束執行通知 AFNetworkingTaskDidSuspendNotification :任務暫停執行通知 AFURLSessionDidInvalidateNotification :網絡會話無效通知 AFURLSessionDownloadTaskDidFailToMoveFileNotification :會話的下載任務將臨時下載文件移動指定目錄發生錯誤通知 <2> 通知鍵值: AFNetworkingTaskDidCompleteResponseDataKey :任務的原始響應數據 AFNetworkingTaskDidCompleteSerializedResponseKey :任務響應數據的反序列化對象 AFNetworkingTaskDidCompleteResponseSerializerKey :響應序列化器用於反序列化響應數據 AFNetworkingTaskDidCompleteAssetPathKey :與下載任務關聯的文件路徑 AFNetworkingTaskDidCompleteErrorKey :與任務或者響應反序列化關聯的錯誤
  • 5) AFNetworking 經常使用數據格式組合設置:緩存

    • AFN 內置支持 JSON,Plist 文件和 XML 文件的半自動序列化和反序列化,能夠對 JSON 格式的請求響應數據自動作反序列化,XML 格式數據須要手動反序列化,使用比較方便。AFN 在反序列化數據以前,會判斷服務器返回的 content-Type,若是 content-Type 不符合要求,就放棄反序列化。

    • AFN 默承認以接收的類型:

      • application/json
      • text/json
      • text/javascript
    • 1> 發送二進制數據,接收 JSON,最經常使用的網絡數據格式組合:
      • 發送數據:
        • 二進制數據:AFHTTPRequestSerializer(默認)
      • 接收數據:
        • JSON 數據:AFJSONResponseSerializer(默認)
    • 2> 發送二進制數據,接收 XML:
      • 發送數據:
        • 二進制數據:AFHTTPRequestSerializer(默認)
      • 接收數據:
        • XML SAX 解析:AFXMLParserResponseSerializer
        • XML DOM 解析:AFHTTPResponseSerializer
    • 3> 發送二進制數據,接收二進制數據(下載...):
      • 發送數據:
        • 二進制數據:AFHTTPRequestSerializer(默認)
      • 接收數據:
        • 二進制數據:AFHTTPResponseSerializer
    • 4> 發送 JSON 數據,接收 JSON:
      • 發送數據:
        • JSON 數據:AFJSONRequestSerializer
      • 接收數據:
        • JSON 數據:AFJSONResponseSerializer(默認)
    • 5> 接收 圖像:
      • 基本上都使用 SDWebImage,緩存作的比 AFN 的要好一些
  • 6) AFSecurityPolicy 安全策略:

    • NSURLConnection 已經封裝了 https 鏈接的創建、數據的加密解密功能,咱們直接使用 NSURLConnection 是能夠訪問 https 網站的,但 NSURLConnection 並無驗證證書是否合法,沒法避免中間人攻擊。要作到真正安全通信,須要咱們手動去驗證服務端返回的證書,AFNetworking 中 AFSecurityPolicy 封裝了證書驗證的過程,讓用戶能夠輕易使用,除了去系統信任 CA 機構列表驗證,還支持 SSL Pinning 方式的驗證。

    • 1> AFSecurityPolicy 安全策略模式:

      • AFSSLPinningModeNone:
        • 這個模式表示不作 SSL pinning,只跟瀏覽器同樣在系統的信任機構列表裏驗證服務端返回的證書。若證書是信任機構簽發的就會經過,如果本身服務器生成的證書,這裏是不會經過的。
      • AFSSLPinningModeCertificate:
        • 這個模式表示用證書綁定方式驗證證書,須要客戶端保存有服務端的證書拷貝,這裏驗證分兩步,第一步驗證證書的域名/有效期等信息,第二步是對比服務端返回的證書跟客戶端返回的是否一致。
      • AFSSLPinningModePublicKey:
        • 這個模式一樣是用證書綁定方式驗證,客戶端要有服務端的證書拷貝,只是驗證時只驗證證書裏的公鑰,不驗證證書的有效期等信息。只要公鑰是正確的,就能保證通訊不會被竊聽,由於中間人沒有私鑰,沒法解開經過公鑰加密的數據。
    • 2> HTTPS:

      • 代理方法:

        - (void)URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition, NSURLCredential *))completionHandler
      • 參數:

        NSURLAuthenticationChallenge:身份驗證質詢 protectionSpace:保護空間,在信任受保護空間中的憑據以前,沒法繼續後續的網絡請求。 NSURLSessionAuthChallengeDisposition:對憑據的處置 NSURLSessionAuthChallengeUseCredential :使用指定的憑據。 NSURLSessionAuthChallengePerformDefaultHandling :默認處理,憑據參數會被忽略。 NSURLSessionAuthChallengeCancelAuthenticationChallenge :整個請求將被忽略。 NSURLSessionAuthChallengeRejectProtectionSpace :拒絕本次憑據,嘗試下一次驗證保護空間。
      • 代碼:

        if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) { NSURLCredential *credential = [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust]; completionHandler(NSURLSessionAuthChallengeUseCredential, credential); }
  • 7) AFNetworkReachabilityManager 網絡狀態監測:

    • 狀態:

      AFNetworkReachabilityStatusUnknown          = -1, 網絡狀態未知 AFNetworkReachabilityStatusNotReachable = 0, 無網絡鏈接 AFNetworkReachabilityStatusReachableViaWWAN = 1, 無線網絡(蜂窩移動網絡) AFNetworkReachabilityStatusReachableViaWiFi = 2, WiFi 網絡
    • 屬性:

      networkReachabilityStatus                                       獲取網絡鏈接狀態
      
          isReachable;                                                    網絡是否鏈接
          isReachableViaWiFi;                                             WiFi 是否鏈接
          isReachableViaWWAN;                                             蜂窩網絡 是否鏈接
    • 方法:

      + (instancetype)sharedManager;                                  實例化網絡狀態監測管理器
          + (instancetype)managerForDomain:(NSString *)domain; 實例化 相對於某個域名 網絡狀態監測管理器 + (instancetype)managerForAddress:(const void *)address; 實例化 相對於某個地址 網絡狀態監測管理器 - (void)startMonitoring; 開啓監聽網絡狀態 - (void)stopMonitoring; 關閉網絡狀態監聽 - (NSString *)localizedNetworkReachabilityStatusString; 獲取本地化網絡狀態字符串 AFStringFromNetworkReachabilityStatus(AFNetworkReachabilityStatus status); 轉換網絡狀態爲字符串格式 - (void)setReachabilityStatusChangeBlock:(void (^)(AFNetworkReachabilityStatus status))block; 網絡狀態改變回調
    • 通知:

      AFNetworkingReachabilityDidChangeNotification                   網絡狀態改變通知
          AFNetworkingReachabilityNotificationStatusItem                  網絡狀態項

二、AFNetworking 的添加

三、AFNetworking 的設置

  • Objective-C

    • Manager 的建立

      // AFHTTPSessionManager AFHTTPSessionManager *manager1 = [AFHTTPSessionManager manager]; NSURL *baseURL2 = [NSURL URLWithString:@"http://192.168.88.200"]; AFHTTPSessionManager *manager2 = [[AFHTTPSessionManager alloc] initWithBaseURL:baseURL2]; NSURL *baseURL3 = [NSURL URLWithString:@"http://192.168.88.200"]; NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration]; AFHTTPSessionManager *manager3 = [[AFHTTPSessionManager alloc] initWithBaseURL:baseURL3 sessionConfiguration:config]; // AFURLSessionManager AFURLSessionManager *manager4 = [[AFURLSessionManager alloc] initWithSessionConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]]; // 取消掛起的 task [[AFURLSessionManager alloc] invalidateSessionCancelingTasks:YES]; 
    • URLRequest 的建立

      NSURL *url1 = [NSURL URLWithString:@"http://192.168.88.200:8080/MJServer/video?type=JSON"]; NSURL *url2 = [NSURL URLWithString:@"http://192.168.88.200:8080/MJServer/video"]; NSString *urlStr = @"http://192.168.88.200:8080/MJServer/video"; NSDictionary *params = @{@"type":@"JSON"}; // GET 建立方式 NSURLRequest *request1 = [NSURLRequest requestWithURL:url1]; NSURLRequest *request2 = [[AFHTTPRequestSerializer serializer] requestWithMethod:@"GET" URLString:urlStr parameters:params error:NULL]; // POST 建立方式 NSMutableURLRequest *request3 = [NSMutableURLRequest requestWithURL:url2]; request3.HTTPMethod = @"POST"; request3.HTTPBody = [@"type=JSON" dataUsingEncoding:NSUTF8StringEncoding]; NSURLRequest *request4 = [[AFHTTPRequestSerializer serializer] requestWithMethod:@"POST" URLString:urlStr parameters:params error:NULL]; NSURLRequest *request5 = [[AFHTTPRequestSerializer serializer] multipartFormRequestWithMethod:@"POST" URLString:urlStr parameters:params constructingBodyWithBlock:^(id<AFMultipartFormData> formData) { } error: NULL];
    • Request 的設置

      AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
      
          NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:@"http://192.168.88.200:8080/MJServer/video?type=JSON"]]; // 設置參數編碼方式 /* `NSUTF8StringEncoding` by default */ manager.requestSerializer.stringEncoding = NSUTF8StringEncoding; // 設置緩存策略 /* `NSURLRequestUseProtocolCachePolicy` by default. */ manager.requestSerializer.cachePolicy = NSURLRequestUseProtocolCachePolicy; request.cachePolicy = NSURLRequestUseProtocolCachePolicy; // 設置網絡服務類型 /* `NSURLNetworkServiceTypeDefault` by default. */ manager.requestSerializer.networkServiceType = NSURLNetworkServiceTypeDefault; request.networkServiceType = NSURLNetworkServiceTypeDefault; // 設置請求超時時間 /* The default timeout interval is 60 seconds. */ manager.requestSerializer.timeoutInterval = 15; request.timeoutInterval = 15; // 是否容許蜂窩網絡訪問 /* `YES` by default. */ manager.requestSerializer.allowsCellularAccess = YES; request.allowsCellularAccess = YES; // 設置是否應用默認的 Cookies /* `YES` by default. */ manager.requestSerializer.HTTPShouldHandleCookies = YES; request.HTTPShouldHandleCookies = YES; // 設置是否使用 Pipelining /* `NO` by default. */ manager.requestSerializer.HTTPShouldUsePipelining = NO; request.HTTPShouldUsePipelining = NO; // 請求頭設置 [manager.requestSerializer setValue:@"iPhone" forHTTPHeaderField:@"User-Agent"]; [request setValue:@"iPhone" forHTTPHeaderField:@"User-Agent"]; // 設置用戶驗證 [manager.requestSerializer setAuthorizationHeaderFieldWithUsername:@"admin" password:@"adminpasswd"]; NSString *username = @"admin"; NSString *password = @"adminpasswd"; NSString *userPasswordString = [NSString stringWithFormat:@"%@:%@", username, password]; NSData *userPasswordData = [userPasswordString dataUsingEncoding:NSUTF8StringEncoding]; NSString *base64EncodedCredential = [userPasswordData base64EncodedStringWithOptions:0]; NSString *authString = [NSString stringWithFormat:@"Basic: %@", base64EncodedCredential]; [request setValue:authString forHTTPHeaderField:@"Authorization"]; // 清除用戶驗證信息 [manager.requestSerializer clearAuthorizationHeader]; [request setValue:nil forHTTPHeaderField:@"Authorization"]; // 設置請求體 request.HTTPBody = [@"type=JSON" dataUsingEncoding:NSUTF8StringEncoding]; // 設置請求模式 // 單獨設置 /* 默認是 GET */ request.HTTPMethod = @"POST"; // 直接設置 NSString *urlStr = @"http://192.168.88.200:8080/MJServer/video"; NSDictionary *parameters = @{@"type":@"XML"}; NSURLRequest *request1 = [[AFHTTPRequestSerializer serializer] requestWithMethod:@"POST" URLString:urlStr parameters:parameters error:NULL];
    • 設置數據請求格式

      NSString *urlStr = @"http://example.com"; NSDictionary *parameters = @{@"foo": @"bar", @"baz": @[@1, @2, @3]}; AFHTTPSessionManager *manager = [AFHTTPSessionManager manager]; // 二進制 格式 // POST http://example.com/ // Content-Type: application/x-www-form-urlencoded // foo=bar&baz[]=1&baz[]=2&baz[]=3 manager.requestSerializer = [AFHTTPRequestSerializer serializer]; // 默認 NSURLRequest *request1 = [[AFHTTPRequestSerializer serializer] requestWithMethod:@"POST" URLString:urlStr parameters:parameters error:NULL]; // JSON 格式 // POST http://example.com/ // Content-Type: application/json // {"foo": "bar", "baz": [1,2,3]} manager.requestSerializer = [AFJSONRequestSerializer serializer]; NSURLRequest *request2 = [[AFJSONRequestSerializer serializer] requestWithMethod:@"POST" URLString:urlStr parameters:parameters error:NULL]; // Plist 格式 manager.requestSerializer = [AFPropertyListRequestSerializer serializer]; NSURLRequest *request3 = [[AFPropertyListRequestSerializer serializer] requestWithMethod:@"POST" URLString:urlStr parameters:parameters error:NULL];
    • 設置數據響應格式

      AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
      
          AFURLSessionManager *manager1 = [[AFURLSessionManager alloc] 
                                            initWithSessionConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]]; // 二進制 manager.responseSerializer = [AFHTTPResponseSerializer serializer]; // JSON,默認,application/json, text/json, text/javascript manager.responseSerializer = [AFJSONResponseSerializer serializer]; // XMLParser,SAX 解析 manager.responseSerializer = [AFXMLParserResponseSerializer serializer]; // Plist manager.responseSerializer = [AFPropertyListResponseSerializer serializer]; // Image manager.responseSerializer = [AFImageResponseSerializer serializer]; // Compound manager.responseSerializer = [AFCompoundResponseSerializer serializer];
    • AFHTTPSessionManager 請求

      // GET // DEPRECATED_ATTRIBUTE - (nullable NSURLSessionDataTask *)GET:(NSString *)URLString parameters:(nullable id)parameters success:(nullable void (^)(NSURLSessionDataTask *task, id _Nullable responseObject))success failure:(nullable void (^)(NSURLSessionDataTask * _Nullable task, NSError *error))failure; - (nullable NSURLSessionDataTask *)GET:(NSString *)URLString parameters:(nullable id)parameters progress:(nullable void (^)(NSProgress *downloadProgress))downloadProgress success:(nullable void (^)(NSURLSessionDataTask *task, id _Nullable responseObject))success failure:(nullable void (^)(NSURLSessionDataTask * _Nullable task, NSError *error))failure; // HEAD - (nullable NSURLSessionDataTask *)HEAD:(NSString *)URLString parameters:(nullable id)parameters success:(nullable void (^)(NSURLSessionDataTask *task))success failure:(nullable void (^)(NSURLSessionDataTask * _Nullable task, NSError *error))failure; // POST // DEPRECATED_ATTRIBUTE - (nullable NSURLSessionDataTask *)POST:(NSString *)URLString parameters:(nullable id)parameters success:(nullable void (^)(NSURLSessionDataTask *task, id _Nullable responseObject))success failure:(nullable void (^)(NSURLSessionDataTask * _Nullable task, NSError *error))failure; - (nullable NSURLSessionDataTask *)POST:(NSString *)URLString parameters:(nullable id)parameters progress:(nullable void (^)(NSProgress *uploadProgress))uploadProgress success:(nullable void (^)(NSURLSessionDataTask *task, id _Nullable responseObject))success failure:(nullable void (^)(NSURLSessionDataTask * _Nullable task, NSError *error))failure; // DEPRECATED_ATTRIBUTE - (nullable NSURLSessionDataTask *)POST:(NSString *)URLString parameters:(nullable id)parameters constructingBodyWithBlock:(nullable void (^)(id <AFMultipartFormData> formData))block success:(nullable void (^)(NSURLSessionDataTask *task, id _Nullable responseObject))success failure:(nullable void (^)(NSURLSessionDataTask * _Nullable task, NSError *error))failure; - (nullable NSURLSessionDataTask *)POST:(NSString *)URLString parameters:(nullable id)parameters constructingBodyWithBlock:(nullable void (^)(id <AFMultipartFormData> formData))block progress:(nullable void (^)(NSProgress *uploadProgress))uploadProgress success:(nullable void (^)(NSURLSessionDataTask *task, id _Nullable responseObject))success failure:(nullable void (^)(NSURLSessionDataTask * _Nullable task, NSError *error))failure; // PUT - (nullable NSURLSessionDataTask *)PUT:(NSString *)URLString parameters:(nullable id)parameters success:(nullable void (^)(NSURLSessionDataTask *task, id _Nullable responseObject))success failure:(nullable void (^)(NSURLSessionDataTask * _Nullable task, NSError *error))failure; // PATCH - (nullable NSURLSessionDataTask *)PATCH:(NSString *)URLString parameters:(nullable id)parameters success:(nullable void (^)(NSURLSessionDataTask *task, id _Nullable responseObject))success failure:(nullable void (^)(NSURLSessionDataTask * _Nullable task, NSError *error))failure; // DELETE - (nullable NSURLSessionDataTask *)DELETE:(NSString *)URLString parameters:(nullable id)parameters success:(nullable void (^)(NSURLSessionDataTask *task, id _Nullable responseObject))success failure:(nullable void (^)(NSURLSessionDataTask * _Nullable task, NSError *error))failure;
    • AFURLSessionManager 請求

      // Data Tasks - (NSURLSessionDataTask *)dataTaskWithRequest:(NSURLRequest *)request completionHandler:(nullable void (^)(NSURLResponse *response, id _Nullable responseObject, NSError * _Nullable error))completionHandler; - (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; // Upload Tasks - (NSURLSessionUploadTask *)uploadTaskWithRequest:(NSURLRequest *)request fromFile:(NSURL *)fileURL progress:(nullable void (^)(NSProgress *uploadProgress))uploadProgressBlock completionHandler:(nullable void (^)(NSURLResponse *response, id _Nullable responseObject, NSError * _Nullable error))completionHandler; - (NSURLSessionUploadTask *)uploadTaskWithRequest:(NSURLRequest *)request fromData:(nullable NSData *)bodyData progress:(nullable void (^)(NSProgress *uploadProgress))uploadProgressBlock completionHandler:(nullable void (^)(NSURLResponse *response, id _Nullable responseObject, NSError * _Nullable error))completionHandler; - (NSURLSessionUploadTask *)uploadTaskWithStreamedRequest:(NSURLRequest *)request progress:(nullable void (^)(NSProgress *uploadProgress))uploadProgressBlock completionHandler:(nullable void (^)(NSURLResponse *response, id _Nullable responseObject, NSError * _Nullable error))completionHandler; // Download Tasks - (NSURLSessionDownloadTask *)downloadTaskWithRequest:(NSURLRequest *)request progress:(nullable void (^)(NSProgress *downloadProgress))downloadProgressBlock destination:(nullable NSURL * (^)(NSURL *targetPath, NSURLResponse *response))destination completionHandler:(nullable void (^)(NSURLResponse *response, NSURL * _Nullable filePath, NSError * _Nullable error))completionHandler; - (NSURLSessionDownloadTask *)downloadTaskWithResumeData:(NSData *)resumeData progress:(nullable void (^)(NSProgress *downloadProgress))downloadProgressBlock destination:(nullable NSURL * (^)(NSURL *targetPath, NSURLResponse *response))destination completionHandler:(nullable void (^)(NSURLResponse *response, NSURL * _Nullable filePath, NSError * _Nullable error))completionHandler;

四、AFNetworking 網絡狀態監測

  • Objective-C

    • 網絡鏈接狀態:

      AFNetworkReachabilityStatusUnknown          = -1, 網絡狀態未知 AFNetworkReachabilityStatusNotReachable = 0, 無網絡鏈接 AFNetworkReachabilityStatusReachableViaWWAN = 1, 無線網絡(蜂窩移動網絡) AFNetworkReachabilityStatusReachableViaWiFi = 2, WiFi 網絡
    • 因爲檢測網絡有必定的延遲,若是啓動 App 當即去檢測調用 [AFNetworkReachabilityManager sharedManager].networkReachabilityStatus 有可能獲得的是 netStatus == AFNetworkReachabilityStatusUnknown; 可是此時明明是有網的,建議在收到監聽網絡狀態回調之後再取 [AFNetworkReachabilityManager sharedManager].networkReachabilityStatus。或者延時調用 [self performSelector:@selector(networkReachability:) withObject:nil afterDelay:0.35f];。

    • 必須開啓監聽,才能得到網絡狀態。

      • AFNetworkReachabilityManager 方式

        // 開啓監聽網絡狀態 [[AFNetworkReachabilityManager sharedManager] startMonitoring]; // 關閉網絡狀態監聽 [[AFNetworkReachabilityManager sharedManager] stopMonitoring]; // 監聽網絡狀態回調 [[AFNetworkReachabilityManager sharedManager] setReachabilityStatusChangeBlock:^(AFNetworkReachabilityStatus status) { // 開啓網絡狀態監聽後,只要網絡狀態發生改變就會調用該 Block 代碼段 }]; // 判斷網絡是否鏈接 BOOL isReachable = [AFNetworkReachabilityManager sharedManager].isReachable; // 判斷 WiFi 是否鏈接 BOOL isReachableViaWiFi = [AFNetworkReachabilityManager sharedManager].isReachableViaWiFi; // 判斷 無線網絡 是否鏈接 BOOL isReachableViaWWAN = [AFNetworkReachabilityManager sharedManager].isReachableViaWWAN; // 獲取網絡鏈接狀態 AFNetworkReachabilityStatus netStatus = [AFNetworkReachabilityManager sharedManager].networkReachabilityStatus; // 轉換網絡狀態爲字符串格式 NSString *netStatusStr1 = AFStringFromNetworkReachabilityStatus(netStatus); // 獲取網絡鏈接狀態 NSString *netStatusStr2 = [[AFNetworkReachabilityManager sharedManager] localizedNetworkReachabilityStatusString];
      • AFHTTPSessionManager/AFURLSessionManager 方式

        AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
        
            AFURLSessionManager * manager = [[AFURLSessionManager alloc] 
                                              initWithSessionConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]]; // 開啓監聽網絡狀態 [manager.reachabilityManager startMonitoring]; NSOperationQueue *operationQueue = manager.operationQueue; [manager.reachabilityManager setReachabilityStatusChangeBlock:^(AFNetworkReachabilityStatus status) { // 開啓網絡狀態監聽後,只要網絡狀態發生改變就回調用該 Block 代碼段 NSString *netStatus = AFStringFromNetworkReachabilityStatus(status); NSLog(@"Reachability: %@", netStatus); switch (status) { case AFNetworkReachabilityStatusReachableViaWWAN: case AFNetworkReachabilityStatusReachableViaWiFi: // 繼續 queue [operationQueue setSuspended:NO]; break; case AFNetworkReachabilityStatusNotReachable: default: // 暫停 queue [operationQueue setSuspended:YES]; break; } }];

五、AFNetworking 安全策略設置

  • Objective-C

    • AFSecurityPolicy 方式

      AFSecurityPolicy *securityPolicy = [AFSecurityPolicy defaultPolicy];
      
          // 設置是否信任無效或過時的 SSL 證書的服務器。默認爲否 securityPolicy.allowInvalidCertificates = YES; // 設置安全驗證模式,默認爲 AFSSLPinningModeNone securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModePublicKey]; 
    • AFHTTPSessionManager/AFURLSessionManager 方式

      AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
      
          AFURLSessionManager * manager = [[AFURLSessionManager alloc] 
                                            initWithSessionConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]]; // 設置是否信任無效或過時的 SSL 證書的服務器。默認爲否 manager.securityPolicy.allowInvalidCertificates = YES; // 設置安全驗證模式,默認爲 AFSSLPinningModeNone manager.securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModePublicKey];

六、AFHTTPRequestOperationManager 的使用

  • Objective-C

    • Manager 的建立

      NSURL *baseURL = [NSURL URLWithString:@"http://192.168.88.200"]; AFHTTPRequestOperationManager *manager1 = [AFHTTPRequestOperationManager manager]; AFHTTPRequestOperationManager *manager2 = [[AFHTTPRequestOperationManager alloc] initWithBaseURL:baseURL];
    • 設置數據請求格式

      AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
      
          // 二進制,默認 manager.requestSerializer = [AFHTTPRequestSerializer serializer]; // JSON manager.requestSerializer = [AFJSONRequestSerializer serializer]; // Plist manager.requestSerializer = [AFPropertyListRequestSerializer serializer];
    • 設置數據響應格式

      AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
      
          // 二進制 manager.responseSerializer = [AFHTTPResponseSerializer serializer]; // JSON,默認 manager.responseSerializer = [AFJSONResponseSerializer serializer]; // XMLParser,SAX 解析 manager.responseSerializer = [AFXMLParserResponseSerializer serializer]; // Plist manager.responseSerializer = [AFPropertyListResponseSerializer serializer]; // Image manager.responseSerializer = [AFImageResponseSerializer serializer]; // Compound manager.responseSerializer = [AFCompoundResponseSerializer serializer];
    • GET 請求

      • 數據請求

        NSString *urlStr = @"http://192.168.88.200/demo.json"; AFHTTPRequestOperationManager *manger = [AFHTTPRequestOperationManager manager]; [manger GET:urlStr parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) { NSLog(@"success: %@ --- %@", responseObject, [responseObject class]); } failure:^(AFHTTPRequestOperation *operation, NSError *error) { NSLog(@"failure: %@", error); }];
      • 文件下載

        NSString *urlStr = @"http://192.168.88.200/download/file/minion_01.mp4"; AFHTTPRequestOperationManager *manger = [AFHTTPRequestOperationManager manager]; // 設置接收數據的類型爲二進制格式 manger.responseSerializer = [AFHTTPResponseSerializer serializer]; [manger GET:urlStr parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) { [responseObject writeToFile:[operation.response.suggestedFilename q_appendDocumentPath] atomically:YES]; NSLog(@"success: %@", [responseObject class]); } failure:^(AFHTTPRequestOperation *operation, NSError *error) { NSLog(@"failure: %@", error); }];
    • HEAD 請求

      NSString *urlStr = @"http://192.168.88.200/download/file/minion_01.mp4"; AFHTTPRequestOperationManager *manger = [AFHTTPRequestOperationManager manager]; [manger HEAD:urlStr parameters:nil success:^(AFHTTPRequestOperation *operation) { NSLog(@"success: %@ --- %lld", operation.response.suggestedFilename, operation.response.expectedContentLength); } failure:^(AFHTTPRequestOperation *operation, NSError *error) { NSLog(@"failure: %@", error); }];
    • POST 請求

      • 數據請求

        NSString *urlStr = @"http://192.168.88.200:8080/MJServer/video"; NSDictionary *params = @{@"type":@"JSON"}; AFHTTPRequestOperationManager *manger = [AFHTTPRequestOperationManager manager]; [manger POST:urlStr parameters:params success:^(AFHTTPRequestOperation *operation, id responseObject) { NSLog(@"success: %@ --- %@", responseObject, [responseObject class]); } failure:^(AFHTTPRequestOperation *operation, NSError *error) { NSLog(@"failure: %@", error); }];
      • 文件上傳

        NSString *urlStr = @"http://192.168.88.200/upload/upload.php"; AFHTTPRequestOperationManager *manger = [AFHTTPRequestOperationManager manager]; [manger POST:urlStr parameters:nil constructingBodyWithBlock:^(id<AFMultipartFormData> formData) { NSData *fileData = [NSData dataWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"HQ_0005.jpg" ofType:nil]]; [formData appendPartWithFileData:fileData name:@"userfile" fileName:@"test.jpg" mimeType:@"image/jpg"]; [formData appendPartWithFormData:[@"qian" dataUsingEncoding:NSUTF8StringEncoding] name:@"username"]; } success:^(AFHTTPRequestOperation *operation, id responseObject) { NSLog(@"success: %@ --- %@", responseObject, [responseObject class]); } failure:^(AFHTTPRequestOperation *operation, NSError *error) { NSLog(@"failure: %@", error); }];

七、AFHTTPSessionManager 的使用

  • Objective-C

    • Manager 的建立

      NSURL *baseURL = [NSURL URLWithString:@"http://192.168.88.200"]; NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration]; AFHTTPSessionManager *manager1 = [AFHTTPSessionManager manager]; AFHTTPSessionManager *manager2 = [[AFHTTPSessionManager alloc] initWithBaseURL:baseURL]; AFHTTPSessionManager *manager3 = [[AFHTTPSessionManager alloc] initWithBaseURL:baseURL sessionConfiguration:config];
    • 設置數據請求格式

      AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
      
          // 二進制,默認 manager.requestSerializer = [AFHTTPRequestSerializer serializer]; // JSON manager.requestSerializer = [AFJSONRequestSerializer serializer]; // Plist manager.requestSerializer = [AFPropertyListRequestSerializer serializer];
    • 設置數據響應格式

      AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
      
          // 二進制 manager.responseSerializer = [AFHTTPResponseSerializer serializer]; // JSON,默認 manager.responseSerializer = [AFJSONResponseSerializer serializer]; // XMLParser,SAX 解析 manager.responseSerializer = [AFXMLParserResponseSerializer serializer]; // Plist manager.responseSerializer = [AFPropertyListResponseSerializer serializer]; // Image manager.responseSerializer = [AFImageResponseSerializer serializer]; // Compound manager.responseSerializer = [AFCompoundResponseSerializer serializer];
    • Request 設置

      AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
      
          // 設置參數編碼方式,`NSUTF8StringEncoding` by default manager.requestSerializer.stringEncoding = NSUTF8StringEncoding; // 設置緩存策略,`NSURLRequestUseProtocolCachePolicy` by default. manager.requestSerializer.cachePolicy = NSURLRequestUseProtocolCachePolicy; // 設置網絡服務類型,`NSURLNetworkServiceTypeDefault` by default. manager.requestSerializer.networkServiceType = NSURLNetworkServiceTypeDefault; // 設置請求超時時間,The default timeout interval is 60 seconds. manager.requestSerializer.timeoutInterval = 15; // 是否容許蜂窩網絡訪問,`YES` by default. manager.requestSerializer.allowsCellularAccess = YES; // 設置是否應用默認的 Cookies,`YES` by default. manager.requestSerializer.HTTPShouldHandleCookies = YES; // 設置是否使用 Pipelining,`NO` by default. manager.requestSerializer.HTTPShouldUsePipelining = NO; // 請求頭設置 // 設置請求頭 [manager.requestSerializer setValue:@"iPhone" forHTTPHeaderField:@"User-Agent"]; // 設置用戶驗證 [manager.requestSerializer setAuthorizationHeaderFieldWithUsername:@"admin" password:@"adminpasswd"]; // 清除用戶驗證信息 [manager.requestSerializer clearAuthorizationHeader];
    • GET 請求

      • 數據請求

        NSString *urlStr = @"http://192.168.88.200/demo.json"; AFHTTPSessionManager *manager = [AFHTTPSessionManager manager]; [manager GET:urlStr parameters:nil progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) { NSLog(@"success: %@ --- %@", responseObject, [responseObject class]); } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) { NSLog(@"failure: %@", error); }];
      • 文件下載

        NSString *urlStr = @"http://192.168.88.200/download/file/minion_01.mp4"; AFHTTPSessionManager *manager = [AFHTTPSessionManager manager]; // 設置接收數據的類型爲二進制格式 manager.responseSerializer = [AFHTTPResponseSerializer serializer]; [manager GET:urlStr parameters:nil progress:^(NSProgress * _Nonnull downloadProgress) { float progress = 1.0 * downloadProgress.completedUnitCount / downloadProgress.totalUnitCount; dispatch_async(dispatch_get_main_queue(), ^{ [self.progressBtn q_setButtonWithProgress:progress lineWidth:10 lineColor:nil backgroundColor:[UIColor yellowColor]]; }); } success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) { [responseObject writeToFile:[task.response.suggestedFilename q_appendDocumentPath] atomically:YES]; NSLog(@"success: %@", [responseObject class]); } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) { NSLog(@"failure: %@", error); }];
    • HEAD 請求

      NSString *urlStr = @"http://192.168.88.200/download/file/minion_01.mp4"; AFHTTPSessionManager *manager = [AFHTTPSessionManager manager]; [manager HEAD:urlStr parameters:nil success:^(NSURLSessionDataTask * _Nonnull task) { NSLog(@"success: %@ --- %lld", task.response.suggestedFilename, task.response.expectedContentLength); } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) { NSLog(@"failure: %@", error); }];
    • POST 請求

      • 數據請求

        NSString *urlStr = @"http://192.168.88.200:8080/MJServer/video"; NSDictionary *params = @{@"type":@"JSON"}; AFHTTPSessionManager *manager = [AFHTTPSessionManager manager]; [manager POST:urlStr parameters:params progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) { NSLog(@"success: %@ --- %@", responseObject, [responseObject class]); } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) { NSLog(@"failure: %@", error); }];
      • 文件上傳

        NSString *urlStr = @"http://192.168.88.200/upload/upload.php"; AFHTTPSessionManager *manager = [AFHTTPSessionManager manager]; [manager POST:urlStr parameters:nil constructingBodyWithBlock:^(id<AFMultipartFormData> _Nonnull formData) { NSData *fileData = [NSData dataWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"HQ_0005.jpg" ofType:nil]]; [formData appendPartWithFileData:fileData name:@"userfile" fileName:@"test.jpg" mimeType:@"image/jpg"]; [formData appendPartWithFormData:[@"qian" dataUsingEncoding:NSUTF8StringEncoding] name:@"username"]; } progress:^(NSProgress * _Nonnull uploadProgress) { float progress = 1.0 * uploadProgress.completedUnitCount / uploadProgress.totalUnitCount; dispatch_async(dispatch_get_main_queue(), ^{ [self.progressBtn q_setButtonWithProgress:progress lineWidth:10 lineColor:nil backgroundColor:[UIColor yellowColor]]; }); } success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) { NSLog(@"success: %@ --- %@", responseObject, [responseObject class]); } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) { NSLog(@"failure: %@", error); }];

八、AFURLSessionManager 的使用

  • Objective-C

    • Manager 的建立

      // 建立 manager AFURLSessionManager *manager = [[AFURLSessionManager alloc] initWithSessionConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]]; // 取消掛起的 task [[AFURLSessionManager alloc] invalidateSessionCancelingTasks:YES];
    • 設置數據響應格式

      AFURLSessionManager *manager = [[AFURLSessionManager alloc] 
                                           initWithSessionConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]]; // 二進制 manager.responseSerializer = [AFHTTPResponseSerializer serializer]; // JSON,默認 manager.responseSerializer = [AFJSONResponseSerializer serializer]; // XMLParser,SAX 解析 manager.responseSerializer = [AFXMLParserResponseSerializer serializer]; // Plist manager.responseSerializer = [AFPropertyListResponseSerializer serializer]; // Image manager.responseSerializer = [AFImageResponseSerializer serializer]; // Compound manager.responseSerializer = [AFCompoundResponseSerializer serializer];
    • 獲取上傳下載進度

      AFURLSessionManager *manager = [[AFURLSessionManager alloc] 
                                           initWithSessionConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]]; // 獲取上傳進度 NSProgress *uploadProgress = [manager uploadProgressForTask:uploadTask]; // 獲取下載進度 NSProgress *downloadProgress = [manager uploadProgressForTask:downloadTask];
    • Data Tasks

      • GET 數據請求

        NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString: @"http://192.168.88.200:8080/MJServer/video?type=JSON"]]; AFURLSessionManager *manager = [[AFURLSessionManager alloc] initWithSessionConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]]; [[manager dataTaskWithRequest:request completionHandler:^(NSURLResponse * _Nonnull response, id _Nullable responseObject, NSError * _Nullable error) { if (error == nil && responseObject != nil) { NSLog(@"success: %@ --- %@", responseObject, [responseObject class]); } else { NSLog(@"failure: %@", error); } }] resume];
      • POST 數據請求

        NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString: @"http://192.168.88.200:8080/MJServer/video"]]; request.HTTPMethod = @"POST"; request.HTTPBody = [@"type=JSON" dataUsingEncoding:NSUTF8StringEncoding]; AFURLSessionManager *manager = [[AFURLSessionManager alloc] initWithSessionConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]]; [[manager dataTaskWithRequest:request completionHandler:^(NSURLResponse * _Nonnull response, id _Nullable responseObject, NSError * _Nullable error) { if (error == nil && responseObject != nil) { NSLog(@"success: %@ --- %@", responseObject, [responseObject class]); } else { NSLog(@"failure: %@", error); } }] resume];
    • Upload Tasks

      • POST 文件上傳

        • 文件數據封裝使用到第三方框架 QExtension,具體實現代碼見 GitHub 源碼 QExtension
        NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString: @"http://192.168.88.200/upload/upload.php"]]; request.HTTPMethod = @"POST"; NSData *fileData = [NSData dataWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"HQ_0005.jpg" ofType:nil]]; NSData *formData = [NSData q_formDataWithRequest:request text:@"qian" textName:@"username" fileData:fileData name:@"userfile" fileName:@"test.jpg" mimeType:@"imge/jpg"]; AFURLSessionManager *manager = [[AFURLSessionManager alloc] initWithSessionConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]]; [[manager uploadTaskWithRequest:request fromData:formData progress:^(NSProgress * _Nonnull uploadProgress) { float progress = 1.0 * uploadProgress.completedUnitCount / uploadProgress.totalUnitCount; dispatch_async(dispatch_get_main_queue(), ^{ [self.progressBtn q_setButtonWithProgress:progress lineWidth:10 lineColor:nil backgroundColor:[UIColor yellowColor]]; }); } completionHandler:^(NSURLResponse * _Nonnull response, id _Nullable responseObject, NSError * _Nullable error) { if (error == nil && responseObject != nil) { NSLog(@"success: %@ --- %@", responseObject, [responseObject class]); } else { NSLog(@"failure: %@", error); } }] resume];
      • POST 文件上傳,fileData 形式

        NSString *urlStr = @"http://192.168.88.200/upload/upload.php"; NSMutableURLRequest *request = [[AFHTTPRequestSerializer serializer] multipartFormRequestWithMethod:@"POST" URLString:urlStr parameters:nil constructingBodyWithBlock:^(id<AFMultipartFormData> _Nonnull formData) { // 指定文件數據形式上傳 NSData *fileData = [NSData dataWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"HQ_0005.jpg" ofType:nil]]; [formData appendPartWithFileData:fileData name:@"userfile" fileName:@"test.jpg" mimeType:@"imge/jpg"]; [formData appendPartWithFormData:[@"qian" dataUsingEncoding:NSUTF8StringEncoding] name:@"username"]; } error: NULL]; AFURLSessionManager *manager = [[AFURLSessionManager alloc] initWithSessionConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]]; [[manager uploadTaskWithStreamedRequest:request progress:^(NSProgress * _Nonnull uploadProgress) { float progress = 1.0 * uploadProgress.completedUnitCount / uploadProgress.totalUnitCount; dispatch_async(dispatch_get_main_queue(), ^{ [self.progressBtn q_setButtonWithProgress:progress lineWidth:10 lineColor:nil backgroundColor:[UIColor yellowColor]]; }); } completionHandler:^(NSURLResponse * _Nonnull response, id _Nullable responseObject, NSError * _Nullable error) { if (error == nil && responseObject != nil) { NSLog(@"success: %@ --- %@", responseObject, [responseObject class]); } else { NSLog(@"failure: %@", error); } }] resume];
      • POST 文件上傳,fileUrl 形式

        NSString *urlStr = @"http://192.168.88.200/upload/upload.php"; NSMutableURLRequest *urlRequest = [[AFHTTPRequestSerializer serializer] multipartFormRequestWithMethod:@"POST" URLString:urlStr parameters:nil constructingBodyWithBlock:^(id<AFMultipartFormData> _Nonnull formData) { // 指定文件路徑形式上傳 NSURL *fileUrl = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"HQ_0005" ofType:@"jpg"]]; [formData appendPartWithFileURL:fileUrl name:@"userfile" fileName:@"test.png" mimeType:@"image/jpg" error:nil]; [formData appendPartWithFormData:[@"qian" dataUsingEncoding:NSUTF8StringEncoding] name:@"username"]; } error: NULL]; AFURLSessionManager *manager = [[AFURLSessionManager alloc] initWithSessionConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]]; [[manager uploadTaskWithStreamedRequest:urlRequest progress:^(NSProgress * _Nonnull uploadProgress) { float progress = 1.0 * uploadProgress.completedUnitCount / uploadProgress.totalUnitCount; dispatch_async(dispatch_get_main_queue(), ^{ [self.progressBtn q_setButtonWithProgress:progress lineWidth:10 lineColor:nil backgroundColor:[UIColor yellowColor]]; }); } completionHandler:^(NSURLResponse * _Nonnull response, id _Nullable responseObject, NSError * _Nullable error) { if (error == nil && responseObject != nil) { NSLog(@"success: %@ --- %@", responseObject, [responseObject class]); } else { NSLog(@"failure: %@", error); } }] resume];
      • PUT 文件上傳

        NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString: @"http://192.168.88.200/uploads/123.jpg"]]; request.HTTPMethod = @"PUT"; [request setValue:[@"admin:adminpasswd" q_basic64AuthEncode] forHTTPHeaderField:@"Authorization"]; NSURL *fileURL = [[NSBundle mainBundle] URLForResource:@"HQ_0005.jpg" withExtension:nil]; AFURLSessionManager *manager = [[AFURLSessionManager alloc] initWithSessionConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]]; manager.responseSerializer = [AFHTTPResponseSerializer serializer]; [[manager uploadTaskWithRequest:request fromFile:fileURL progress:^(NSProgress * _Nonnull uploadProgress) { float progress = 1.0 * uploadProgress.completedUnitCount / uploadProgress.totalUnitCount; dispatch_async(dispatch_get_main_queue(), ^{ [self.progressBtn q_setButtonWithProgress:progress lineWidth:10 lineColor:nil backgroundColor:[UIColor yellowColor]]; }); } completionHandler:^(NSURLResponse * _Nonnull response, id _Nullable responseObject, NSError * _Nullable error) { if (error == nil && responseObject != nil) { NSLog(@"success: %@ --- %@", responseObject, [responseObject class]); } else { NSLog(@"failure: %@", error); } }] resume];
    • Download Tasks

      • 普通下載

        NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://192.168.88.200/download/file/minion_01.mp4"]]; AFURLSessionManager *manager = [[AFURLSessionManager alloc] initWithSessionConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]]; [[manager downloadTaskWithRequest:request progress:^(NSProgress * _Nonnull downloadProgress) { float progress = 1.0 * downloadProgress.completedUnitCount / downloadProgress.totalUnitCount; dispatch_async(dispatch_get_main_queue(), ^{ [self.progressBtn q_setButtonWithProgress:progress lineWidth:10 lineColor:nil backgroundColor:[UIColor yellowColor]]; }); } destination:^NSURL * _Nonnull(NSURL * _Nonnull targetPath, NSURLResponse * _Nonnull response) { return [NSURL fileURLWithPath:[response.suggestedFilename q_appendDocumentPath]]; } completionHandler:^(NSURLResponse * _Nonnull response, NSURL * _Nullable filePath, NSError * _Nullable error) { if (error == nil) { NSLog(@"success: %@ --- %@", response, [response class]); } else { NSLog(@"failure: %@", error); } }] resume];
      • 斷點下載

        @property (nonatomic, strong) AFURLSessionManager *manager; @property (nonatomic, retain) NSURLSessionDownloadTask *downloadTask; @property (nonatomic, strong) NSData *resumeData; @property (nonatomic, strong) NSString *resumeTmpPath; @property (nonatomic, assign) BOOL isDownloading; @property (nonatomic, assign) BOOL isPause; - (AFURLSessionManager *)manager { if (_manager == nil) { _manager = [[AFURLSessionManager alloc] initWithSessionConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]]; _manager.responseSerializer = [AFHTTPResponseSerializer serializer]; } return _manager; } - (NSString *)resumeTmpPath { if (_resumeTmpPath == nil) { _resumeTmpPath = [@"resumeTmpData.tmp" q_appendCachePath]; } return _resumeTmpPath; } // 開始下載 - (void)start { if (self.isDownloading) { NSLog(@"已經開始下載"); return; } if (self.isPause) { NSLog(@"繼續下載"); [self.downloadTask resume]; self.isPause = NO; self.isDownloading = YES; return; } if (![[NSFileManager defaultManager] fileExistsAtPath:self.resumeTmpPath]) { NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString: @"http://120.25.226.186:32812/resources/videos/minion_01.mp4"]]; self.downloadTask = [self.manager downloadTaskWithRequest:request progress:^(NSProgress * _Nonnull downloadProgress) { [self downloadProgress:downloadProgress]; } destination:^NSURL * _Nonnull(NSURL * _Nonnull targetPath, NSURLResponse * _Nonnull response) { return [NSURL fileURLWithPath:[response.suggestedFilename q_appendDocumentPath]]; } completionHandler:^(NSURLResponse * _Nonnull response, NSURL * _Nullable filePath, NSError * _Nullable error) { [self downloadCompletion:filePath error:error]; }]; [self.downloadTask resume]; self.isPause = NO; self.isDownloading = YES; } else { [self goon]; } } // 繼續下載 - (void)goon { if (self.isDownloading) { NSLog(@"已經開始下載"); return; } if (self.isPause) { [self.downloadTask resume]; NSLog(@"繼續下載"); } else { self.resumeData = [NSData dataWithContentsOfFile:self.resumeTmpPath]; self.downloadTask = [self.manager downloadTaskWithResumeData:self.resumeData progress:^(NSProgress * _Nonnull downloadProgress) { [self downloadProgress:downloadProgress]; } destination:^NSURL * _Nonnull(NSURL * _Nonnull targetPath, NSURLResponse * _Nonnull response) { return [NSURL fileURLWithPath:[response.suggestedFilename q_appendDocumentPath]]; } completionHandler:^(NSURLResponse * _Nonnull response, NSURL * _Nullable filePath, NSError * _Nullable error) { [self downloadCompletion:filePath error:error]; }]; [self.downloadTask resume]; NSLog(@"繼續下載"); } self.isPause = NO; self.isDownloading = YES; } // 暫停下載 - (void)pause { if (!self.isDownloading) { NSLog(@"已經中止下載"); return; } [self.downloadTask suspend]; NSLog(@"暫停下載"); self.isPause = YES; self.isDownloading = NO; } // 中止下載 - (void)stop { if (!self.isDownloading) { NSLog(@"已經中止下載"); return; } [self.downloadTask cancelByProducingResumeData:^(NSData * _Nullable resumeData) { if (resumeData) { self.resumeData = resumeData; [self.resumeData writeToFile:self.resumeTmpPath atomically:YES]; } self.downloadTask = nil; NSLog(@"中止下載"); }]; self.isDownloading = NO; } - (void)downloadProgress:(NSProgress *)downloadProgress { float progress = 1.0 * downloadProgress.completedUnitCount / downloadProgress.totalUnitCount; dispatch_async(dispatch_get_main_queue(), ^{ [self.progressBtn q_setButtonWithProgress:progress lineWidth:10 lineColor:nil backgroundColor:[UIColor yellowColor]]; }); } - (void)downloadCompletion:(NSURL *)filePath error:(NSError *)error { self.isDownloading = NO; if (error == nil) { NSLog(@"success: %@", filePath.path); [[NSFileManager defaultManager] removeItemAtPath:self.resumeTmpPath error:nil]; } else { NSLog(@"%@", error); if (error) { NSLog(@"failure: %@", error.userInfo[NSLocalizedDescriptionKey]); self.resumeData = error.userInfo[NSURLSessionDownloadTaskResumeData]; } if ([error.localizedFailureReason isEqualToString:@"No such file or directory"]) { [[NSFileManager defaultManager] removeItemAtPath:self.resumeTmpPath error:nil]; [self start]; } } }

九、AFNetworking 單例封裝

  • Objective-C

    • NetworkTools.h

      #import <AFNetworking/AFNetworking.h> @interface NetworkTools : AFHTTPSessionManager + (instancetype)sharedNetworkTools; @end
    • NetworkTools.m

      @implementation NetworkTools + (instancetype)sharedNetworkTools { static NetworkTools *tools; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ // baseURL 的目的,就是讓後續的網絡訪問直接使用 相對路徑便可,baseURL 的路徑必定要有 / 結尾 NSURL *baseURL = [NSURL URLWithString:@"http://c.m.163.com/"]; NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration]; tools = [[self alloc] initWithBaseURL:baseURL sessionConfiguration:config]; // 修改 解析數據格式 可以接受的內容類型 - 官方推薦的作法,民間作法:直接修改 AFN 的源代碼 tools.responseSerializer.acceptableContentTypes = [NSSet setWithObjects:@"application/json", @"text/json", @"text/javascript", @"text/html", nil]; }); return tools; } @end
相關文章
相關標籤/搜索