iOS - ASIHTTPRequest 網絡請求

前言

  • 使用 iOS SDK 中的 HTTP 網絡請求 API,至關的複雜,調用很繁瑣,ASIHTTPRequest 就是一個對 CFNetwork API 進行了封裝,而且使用起來很是簡單的一套 API,外號 「HTTP終結者」,用 Objective-C 編寫,運行效率很高,能夠很好的應用在 Mac OS X 系統和 iOS 平臺的應用程序中,ASIHTTPRequest 適用於基本的 HTTP 請求,和基於 REST 的服務之間的交互。惋惜做者早已中止更新,有一些潛在的 BUG 無人去解決,不少公司的舊項目裏面都殘留着它的身影,之前的不少 iOS 項目都是 ASI + SBJson,會不會用 ASI,能夠算是檢驗是否爲老牌 iOS 程序員的標準之一。從 iOS 9 開始 CFNetwork 相關的類和方法開始被廢棄,可使用 AFNetworking 替換 ASIHTTPRequest 的使用。在 iOS 9+ 中使用 ASIHTTPRequest 無需對 App Transport Security Settings 添加設置。

一、ASIHTTPRequest

1.1 ASI 主要特點

  • 經過簡單的接口,便可完成向服務端提交數據和從服務端獲取數據的工做。
  • 下載的數據,可存儲到內存中或直接存儲到磁盤中。
  • 能上傳本地文件到服務端。
  • 能夠方便的訪問和操做請求和返回的 Http 頭信息。
  • 能夠獲取到上傳或下載的進度信息,爲應用程序提供更好的體驗。
  • 支持上傳或下載隊列,而且可獲取隊列的進度信息。
  • 支持基本、摘要和 NTLM 身份認證,在同一會話中受權憑證會自動維持,而且能夠存儲在 Keychain(Mac 和 iOS 操做系統的密碼管理系統)中。
  • 支持 Cookie。
  • 當應用(iOS 4+)在後臺運行時,請求能夠繼續運行。
  • 支持 GZIP 壓縮數據。
  • 內置的 ASIDownloadCache 類,能夠緩存請求返回的數據,這樣即便沒有網絡也能夠返回已經緩存的數據結果。
  • ASIWebPageRequest 能夠下載完整的網頁,包括包含的網頁、樣式表、腳本等資源文件,並顯示在 UIWebView /WebView 中。任意大小的頁面均可以無限期緩存,這樣即便沒有網絡也能夠離線瀏覽。
  • 支持客戶端證書。
  • 支持經過代理髮起 Http 請求。
  • 支持帶寬限制。在 iOS 平臺,能夠根據當前網絡狀況來自動決定是否限制帶寬,例如當使用 WWAN(GPRS/Edge/3G) 網絡時限制,而當使用 WIFI 時不作任何限制。
  • 支持斷點續傳。
  • 支持同步和異步請求。

1.2 AFN 與 ASI 的區別

  • 一、底層實現
    • 1)AFN 的底層實現基於 OC 的 NSURLConnection 和 NSURLSession
    • 2)ASI 的底層實現基於純 C 語言的 CFNetwork 框架
    • 3)由於 NSURLConnection 和 NSURLSession 是在 CFNetwork 之上的一層封裝,所以 ASI 的運行性能高於 AFN
  • 二、對服務器返回的數據處理
    • 1)ASI 沒有直接提供對服務器數據處理的方式,直接返回的是 NSData/NSString
    • 2)AFN 提供了多種對服務器數據處理的方式
      • (1) JSON 處理-直接返回 NSDictionary 或者 NSArray
      • (2) XML 處理-返回的是 xml 類型數據,需對其進行解析
      • (3) 其餘類型數據處理
  • 三、監聽請求過程
    • 1)AFN 提供了success 和 failure 兩個 block 來監聽請求的過程(只能監聽成功和失敗)
      • success : 請求成功後調用
      • failure : 請求失敗後調用
    • 2)ASI 提供了 3 套方案,每一套方案都能監聽請求的完整過程(監聽請求開始、接收到響應頭信息、接受到具體數據、接受完畢、請求失敗)
      • 成爲代理,遵照協議,實現協議中的代理方法
      • 成爲代理,不遵照協議,自定義代理方法
      • 設置 block
  • 四、在文件下載和文件上傳的使用難易度
    • 1)AFN
      • 不容易實現監聽下載進度和上傳進度
      • 不容易實現斷點續傳
      • 通常只用來下載不大的文件
    • 2)ASI
      • 很是容易實現下載和上傳
      • 很是容易監聽下載進度和上傳進度
      • 很是容易實現斷點續傳
      • 下載大文件或小文件都可
    • 3)實現下載上傳推薦使用 ASI
  • 五、網絡監控
    • 1)AFN 本身封裝了網絡監控類,易使用
    • 2)ASI 使用的是 Reachability,由於使用 CocoaPods 下載 ASI 時,會同步下載 Reachability,但 Reachability 做爲網絡監控使用較爲複雜(相對於 AFN 的網絡監控類來講)
    • 3)推薦使用 AFN 作網絡監控 AFNetworkReachabilityManager
  • 六、ASI 提供的其餘實用功能
    • 1)控制信號旁邊的圈圈要不要在請求過程當中轉
    • 2)能夠輕鬆地設置請求之間的依賴:每個請求都是一個 NSOperation 對象
    • 3)能夠統一管理全部請求(還專門提供了一個叫作 ASINetworkQueue 來管理全部的請求對象)
      • 暫停/恢復/取消全部的請求
      • 監聽整個隊列中全部請求的下載進度和上傳進度

二、ASIHTTPRequest 的使用

2.1 添加 ASIHTTPRequest

  • Github 網址:
    • https://github.com/pokeb/asi-http-request
    • https://allseeing-i.com/ASIHTTPRequest/
  • ASIHTTPRequest 系統需求:git

    ASIHTTPRequest Version   |    Minimum iOS Target    |    Target Notes

    ---------------------------|--------------------------|---------------------
    1.8.1 -> 1.8.2 | iOS 3.0+ |
    0.2 -> 1.8.0 | |程序員

  • ASIHTTPRequest 使用 MRCgithub

  • Objective-Cweb

    // 添加系統庫文件
        CFNetwork.framework
        SystemConfiguration.framework
        MobileCoreServices.framework
        CoreGraphics.framework
        libz.1.1.3.tbd
        libxml2.2.tbd
    
        // 添加第三方庫文件
        ASIHTTPRequest-1.8.2
    
        // 在 TARGETS -> Builed Settings -> Search Paths -> Header Search Paths 中添加文件路徑
        /usr/include/libxml2
    
        // 在 TARGETS -> Build Phases -> Compile Sources -> ...in .../ASIHTTPRequest 後添加
        -fno-objc-arc
    
        // 包含頭文件
        #import "ASIHTTPRequest.h"
        #import "ASIFormDataRequest.h"

2.2 ASIHTTPRequest 的設置

  • Objective-Capi

    // 設置請求頭
        ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:@"http://api.hudong.com/iphonexml.do?type=focus-c"]];
        [request addRequestHeader:@"Referer" value:@"http://www.dreamingwish.com/"];
    
        // 設置應用後臺運行時是否仍然請求數據
        request.shouldContinueWhenAppEntersBackground = YES;
    
        // 設置請求超時時重試的次數
        request.numberOfTimesToRetryOnTimeout = 3;
    
        // 設置 KeepAlive 支持
    
            // Set the amount of time to hang on to a persistent connection before it should expire to 2 minutes
            request.persistentConnectionTimeoutSeconds = 120;
    
            // Disable persistent connections entirely
            request.shouldAttemptPersistentConnection = NO; 
    
        // 設置是否顯示網絡請求信息在 status bar 上
        [ASIHTTPRequest setShouldUpdateNetworkActivityIndicator:NO];
    
        // 網絡狀態檢查
        BOOL isNetworkInUse = [ASIHTTPRequest isNetworkInUse];

三、ASI 同步 GET 請求

  • 這是 ASIHTTPRequest 最簡單的一種使用模式,發送 startSynchronous 消息後即開始在同一線程中執行 HTTP 請求,線程將一直等待直到請求結束(請求成功或者失敗)。經過檢查 error 屬性能夠判斷請求是否成功或者有錯誤發生。緩存

  • 要獲取返回的文本信息,調用 responseString 方法。若是下載的是二進制文件,例如圖片、MP3,則調用 responseData 方法,能夠獲得一個 NSData 對象。服務器

  • 通常狀況下,應該優先使用異步請求代替同步請求,當在主線程中使用 ASIHTTPRequest 同步請求會阻塞主線程的執行,這致使用戶界面不響應用戶操做,任何動畫都會中止渲染,直到請求完成。網絡

  • Objective-Capp

    • 數據請求框架

      NSURL *url = [NSURL URLWithString:@"http://api.hudong.com/iphonexml.do?type=focus-c"];
      
          // 建立請求
          ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
      
          // 設置超時時間,可不設置,使用默認
          request.timeOutSeconds = 5;
      
          // 發送同步請求
          [request startSynchronous];
      
          // 得到錯誤信息
          NSError *error = [request error];
      
          // 網絡請求失敗
          if (error) {
      
              // 網絡請求成功
              NSLog(@"網絡請求失敗:\n%@", error);
      
          } else {
      
              // 得到服務器的響應,字符串格式
              NSString *responseString = [request responseString];
              NSLog(@"網絡請求成功:\n%@", responseString);
      
              // 得到服務器的響應,NSData 格式
              NSData *responseData = [request responseData];
              textView.text = [[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding];
          }
    • 文件下載

      • 經過設置 request 的 setDownloadDestinationPath,能夠設置下載文件用的下載目標目錄。首先,下載過程文件會保存在 temporaryFileDownloadPath 目錄下。若是下載完成會作如下事情:
        • 1,若是數據是壓縮的,進行解壓,並把文件放在 downloadDestinationPath 目錄中,臨時文件被刪除。
        • 2,若是下載失敗,臨時文件被直接移到 downloadDestinationPath 目錄,並替換同名文件。
      • 若是你想獲取下載中的全部數據,能夠實現 delegate 中的 request:didReceiveData:方法。但若是你實現了這個方法,request 在下載完後,request 並不把文件放在 downloadDestinationPath中,須要手工處理。

        NSURL *url = [NSURL URLWithString:@"http://www.dreamingwish.com/wp-content/uploads/2011/10/asihttprequest-auth.png"];
        
            ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
        
            // 設置文件存儲路徑
            [request setDownloadDestinationPath:@"/Users/JHQ0228/Desktop/asi.png"];
        
            [request startSynchronous];
        
            // 得到錯誤信息
            NSError *error = [request error];
        
            // 網絡請求失敗
            if (error) {
        
                NSLog(@"網絡請求失敗:\n%@", error);
        
            } else {
        
                // 網絡請求成功
                NSLog(@"網絡請求成功:\n");
            }

四、ASI 異步 GET 請求

  • 請求在後臺線程中運行,當請求執行完後再通知調用的線程。這樣不會致使主線程進行網絡請求時,界面被鎖定等狀況。

    • 協議方式

      • 在這裏實現了兩個 delegate 的方法,當數據請求成功時會調用 requestFinished,請求失敗時(如網絡問題或服務器內部錯誤)會調用 requestFailed。

        NSURL *url = [NSURL URLWithString:@"http://api.hudong.com/iphonexml.do?type=focus-c"];
        
            // 建立請求
            ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
        
            // 設置超時時間,可不設置,使用默認
            request.timeOutSeconds = 5;
        
            // 設置代理,需遵照 <ASIHTTPRequestDelegate> 協議
            request.delegate = self;
        
            // 發送異步請求
            [request startAsynchronous];
        
            // 網絡請求成功,協議方法
            - (void)requestFinished:(ASIHTTPRequest *)request {
        
            }
        
            // 網絡請求失敗,協議方法
            - (void)requestFailed:(ASIHTTPRequest *)request {
        
            }
    • Block 方式

      • 在平臺支持狀況下,ASIHTTPRequest 1.8 以上支持 block。

        NSURL *url = [NSURL URLWithString:@"http://api.hudong.com/iphonexml.do?type=focus-c"];
        
            // 建立請求,加 __weak 除去 block 循環調用警告
            __weak ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
        
            // 設置超時時間,可不設置,使用默認
            request.timeOutSeconds = 5;
        
            // 發送異步請求
            [request startAsynchronous];
        
            // 網絡請求成功
            [request setCompletionBlock:^{
        
            }];
        
            // 網絡請求失敗
            [request setFailedBlock:^{
        
            }];

五、ASI POST 請求

  • POST 表單

    • ASIFormDataRequest,模擬 Form 表單提交,其提交格式與 Header 會自動識別。文件中的數據是須要時才從磁盤加載,因此只要 web server 能處理,那麼上傳大文件是沒有問題的。

      // 一般數據是以 ’application/x-www-form-urlencoded’ 格式發送的,若是上傳了二進制數據或者文件,那麼格式將自動變爲 ‘multipart/form-data’。
      
              ASIFormDataRequest *request = [ASIFormDataRequest requestWithURL:[NSURL URLWithString:@"http://www.dreamingwish.com"]];
      
              // 沒有文件
              [request setPostValue:@"Ben" forKey:@"first_name"];
              [request setPostValue:@"Copsey" forKey:@"last_name"];
      
              // 發送文件
              [request setFile:@"/Users/ben/Desktop/ben.jpg" forKey:@"photo"];
      
          // 數據的 mime 頭是自動斷定的,可是若是你想自定義mime頭,那麼這樣:
      
              ASIFormDataRequest *request = [ASIFormDataRequest requestWithURL:[NSURL URLWithString:@"http://www.dreamingwish.com"]];
      
              // Upload a file on disk
              [request setFile:@"/Users/ben/Desktop/ben.jpg" withFileName:@"myphoto.jpg" andContentType:@"image/jpeg" forKey:@"photo"];   
      
              // Upload an NSData instance
              NSData *imageData = UIImagePNGRepresentation([UIImage imageNamed:@"myphoto.jpg"]);
              [request setData:imageData withFileName:@"myphoto.jpg" andContentType:@"image/jpeg" forKey:@"photo"];
      
          // 你可使用 addPostValue 方法來發送相同 name 的多個數據:
      
              ASIFormDataRequest *request = [ASIFormDataRequest requestWithURL:[NSURL URLWithString:@"http://www.dreamingwish.com"]];
      
              [request addPostValue:@"Ben" forKey:@"names"];
              [request addPostValue:@"George" forKey:@"names"];
  • PUT 請求、自定義 POST 請求

    • 若是你想發送 PUT 請求,或者你想自定義 POST 請求,使用 appendPostData: 或者 appendPostDataFromFile:

      ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:@"http://www.dreamingwish.com"]];
      
          [request appendPostData:[@"This is my data" dataUsingEncoding:NSUTF8StringEncoding]];
      
          // Default becomes POST when you use appendPostData: / appendPostDataFromFile: / setPostBody:
          [request setRequestMethod:@"PUT"];
相關文章
相關標籤/搜索