ASIHttpRequest 詳解

 ASIHTTPRequest 是一款極其強勁的 HTTP 訪問開源項目。讓簡單的 API 完成複雜的功能,如:異步請求,隊列請求,GZIP 壓縮,緩存,斷點續傳,進度跟蹤,上傳文件,HTTP 認證。在新的版本中,還加入了 Objective-C 閉包 Block 的支持,讓咱們的代碼加輕簡靈活。緩存

    下面就舉例說明它的 API 用法。安全

發起一個同步請求服務器

    同步意爲着線程阻塞,在主線程中使用此方法會使應用Hang住而不響應任何用戶事件。因此,在應用程序設計時,大多被用在專門的子線程增長用戶體驗,或用異步請求代替(下面會講到)。cookie

    - (IBAction)grabURL:(id)sender
    {
      NSURL *url = [NSURL URLWithString:@"http://allseeing-i.com"];
      ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
      [request startSynchronous];
      NSError *error = [request error];
      if (!error) {
        NSString *response = [request responseString];
      }
    }
網絡

  • 用 requestWithURL 快捷方法獲取 ASIHTTPRequest 的一個實例
  • startSynchronous 方法啓動同步訪問
  • 因爲是同步請求,沒有基於事件的回調方法,因此從 request的error 屬性獲取錯誤信息
  • responseString,爲請求的返回 NSString 信息

建立一個異步請求閉包

    異步請求的好處是不阻塞當前線程,但相對於同步請求略爲複雜,至少要添加兩個回調方法來獲取異步事件。下面異步請求代碼完成上面一樣的一件事情:架構

- (IBAction)grabURLInBackground:(id)sender
{
   NSURL *url = [NSURL URLWithString:@"http://allseeing-i.com"];
   ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
   [request setDelegate:self];
   [request startAsynchronous];
}
 
- (void)requestFinished:(ASIHTTPRequest *)request
{
   // Use when fetching text data
   NSString *responseString = [request responseString];
 
   // Use when fetching binary data
app

   NSData *responseData = [request responseData];
   // 特別注意,若是想使用上面方法獲取返回值,切記不要重寫
didReceiveData 方法,若是重寫了該方法
       就得本身處理返回數據,由於沒有好好看文檔,費了老長時間異步

}
 
- (void)requestFailed:(ASIHTTPRequest *)request
{
   NSError *error = [request error];
}

  • 與上面不一樣的地方是指定了一個 "delegate",並用 startAsynchronous 來啓動網絡請求
  • 在這裏實現了兩個 delegate 的方法,當數據請求成功時會調用 requestFinished,請求失敗時(如網絡問題或服務器內部錯誤)會調用 requestFailed。

隊列請求fetch

    提供了一個對異步請求更加精準豐富的控制。如:能夠設置在隊列中同步請求的鏈接數。往隊列裏添加的請求實例數大於 maxConcurrentOperationCount 時,請求實例將被置爲等待,直到前面至少有一個請求完成並出列才被放到隊列裏執行。這也適用於當咱們有多個請求需求按順序執行的時候(多是業務上的須要,也多是軟件上的調優),僅僅須要把 maxConcurrentOperationCount 設爲「1」。

- (IBAction)grabURLInTheBackground:(id)sender
{
   if (![self queue]) {
      [self setQueue:[[[NSOperationQueue alloc] init] autorelease]];
   }
 
   NSURL *url = [NSURL URLWithString:@"http://allseeing-i.com"];
   ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
   [request setDelegate:self];
   [request setDidFinishSelector:@selector(requestDone:)];
   [request setDidFailSelector:@selector(requestWentWrong:)];
   [[self queue] addOperation:request]; //queue is an NSOperationQueue
}
 
- (void)requestDone:(ASIHTTPRequest *)request
{
   NSString *response = [request responseString];
}
 
- (void)requestWentWrong:(ASIHTTPRequest *)request
{
   NSError *error = [request error];
}

    建立 NSOperationQueue,這個 Cocoa 架構的執行任務(NSOperation)的任務隊列。咱們經過 ASIHTTPRequest.h 的源碼能夠看到,此類自己就是一個 NSOperation 的子類。也就是說它能夠直接被放到"任務隊列"中並被執行。上面的代碼除了隊列的建立與添加操做外,其它代碼與上一例同樣。

隊列異步請求中中獲取或識別不一樣request小技巧

  • 能夠設置一個上下文(userInfo)到 request 對象中,當請求響應完後能夠經過訪問 request 對象的 userInfo 獲取裏面的信息
  • 爲每個請求實例設置不一樣的 setDidFinishSelector / setDidFailSelector 的回調方法
  • 子類化 ASIHTTPRequest,重寫 requestFinished: 與 failWithProblem: 方法

ASINetworkQueues, 它的delegate提供更爲豐富的功能

    提供的更多的回調方法以下:

  •  requestDidStartSelector,請求發起時會調此方法,你能夠在此方法中跟據業務選擇性的設置 request 對象的 deleaget
  • requestDidReceiveResponseHeadersSelector,當接受完響應的 Header 後設計此方法,這個對下載大數據的時候至關有用,你能夠在方法裏作更多業務上的處理
  • requestDidFinishSelector,請求並響應成功完成時調用此方法
  • requestDidFailSelector,請求失敗
  • queueDidFinishSelector,整個隊列裏的全部請求都結束時調用此方法

    它是 NSOperationQueues 的擴展,小而強大。但也與它的父類略有區別。如,僅添加到隊列中其實並不能執行請求,只有調用[  queue g o ]纔會執行;一個正在運行中的隊列,並不須要重複調用[  queue go  ]。默認狀況下,隊列中的一個請求若是失敗,它會取消全部未完成的請求。能夠設置[  queue setShouldCancelAllRequestsOnFailure:NO  ]來修正。

取消異步請求

    首先,同步請求是不能取消的。

    其次,無論是隊列請求,仍是簡單的異步請求,所有調用[ request cancel ]來取消請求。取消的請求默認都會按請求失敗處理,並調用請求失敗delegate。
    若是不想調用delegate方法,則設置:[ request clearDelegatesAndCancel];

    隊列請求中須要注意的是,若是你取消了一個請求,隊列會自動取消其它全部請求。若是隻想取消一個請求,能夠設置隊列:[ queue setShouldCancelAllRequestsOnFailure:NO ]; 若是想明確取消全部請求:[ queue cancelAllOperations ];

安全的內存回收建議

    request並無retain你的delegate,因此在沒有請求完的時候釋放了此delegate,須要在dealloc方法裏先取消全部請求,再釋放請求實例,如:

 - (void)dealloc
{
   [request clearDelegatesAndCancel];
   [request release];
   ...
   [super dealloc];
}

向服務器端上傳數據

    ASIFormDataRequest ,模擬 Form 表單提交,其提交格式與 Header 會自動識別。

  • 沒有文件:application/x-www-form-urlencoded
  • 有文件:multipart/form-data

     ASIFormDataRequest *request = [ASIFormDataRequest requestWithURL:url];
    [request setPostValue:@"Ben" forKey:@"first_name"];
    [request setPostValue:@"Copsey" forKey:@"last_name"];
    [request setFile:@"/Users/ben/Desktop/ben.jpg" forKey:@"photo"];
    [request addData:imageData withFileName:@"george.jpg" andContentType:@"image/jpeg" forKey:@"photos"];

    若是要發送自定義數據:

    ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
    [request appendPostData:[@"This is my data" dataUsingEncoding:NSUTF8StringEncoding]];
    // Default becomes POST when you use appendPostData: / appendPostDataFromFile: / setPostBody:
    [request setRequestMethod:@"PUT"];

下載文件

    經過設置request的setDownloadDestinationPath,能夠設置下載文件用的下載目標目錄。

    首先,下載過程文件會保存在temporaryFileDownloadPath目錄下。若是下載完成會作如下事情:

  • 若是數據是壓縮的,進行解壓,並把文件放在 downloadDestinationPath 目錄中,臨時文件被刪除
  • 若是下載失敗,臨時文件被直接移到 downloadDestinationPath 目錄,並替換同名文件

    若是你想獲取下載中的全部數據,能夠實現 delegate 中的 request:didReceiveData:方法。但若是你實現了這個方法,request 在下載完後,request 並不把文件放在 downloadDestinationPath 中,須要手工處理。

獲取響應信息

    信息:status , header, responseEncoding

    [request responseStatusCode];
    [[request responseHeaders] objectForKey:@"X-Powered-By"];
    [request responseEncoding];

獲取請求進度

 

    有兩個回調方法能夠獲取請求進度:

  • downloadProgressDelegate,能夠獲取下載進度
  • uploadProgressDelegate,能夠獲取上傳進度

 cookie的支持

    若是 Cookie 存在的話,會把這些信息放在 NSHTTPCookieStorage 容器中共享,並供下次使用。你能夠用 [ ASIHTTPRequest setSessionCookies:nil ] ; 清空全部 Cookies。固然,你也能夠取消默認的Cookie策略,而使自定義的Cookie:

    //Create a cookie
    NSDictionary *properties = [[[NSMutableDictionary alloc] init] autorelease];
    [properties setValue:[@"Test Value" encodedCookieValue] forKey:NSHTTPCookieValue];
    [properties setValue:@"ASIHTTPRequestTestCookie" forKey:NSHTTPCookieName];
    [properties setValue:@".allseeing-i.com" forKey:NSHTTPCookieDomain];
    [properties setValue:[NSDate dateWithTimeIntervalSinceNow:60*60] forKey:NSHTTPCookieExpires];
    [properties setValue:@"/asi-http-request/tests" forKey:NSHTTPCookiePath];
    NSHTTPCookie *cookie = [[[NSHTTPCookie alloc] initWithProperties:properties] autorelease];
     
    //This url will return the value of the 'ASIHTTPRequestTestCookie' cookie
    url = [NSURL URLWithString:@"http://allseeing-i.com/ASIHTTPRequest/tests/read_cookie"];
    request = [ASIHTTPRequest requestWithURL:url];
    [request setUseCookiePersistence:NO];
    [request setRequestCookies:[NSMutableArray arrayWithObject:cookie]];
    [request startSynchronous];
     
    //Should be: I have 'Test Value' as the value of 'ASIHTTPRequestTestCookie'
    NSLog(@"%@",[request responseString]);

大文件斷點續傳

    0.94 之後支持大文件的斷點下載,只須要設置

[ request setAllowResumeForFileDownloads:YES ];

[ request setDownloadDestinationPath:downloadPath ];

    就能夠了。

相關文章
相關標籤/搜索