iPhone應(yīng)用開發(fā)中ASIHTTPRequest詳解
iPhone應(yīng)用開發(fā)中ASIHTTPRequest詳解是本文要講解的內(nèi)容,ASIHTTPRequest 是一款極其強勁的 HTTP 訪問開源項目。讓簡單的 API 完成復雜的功能,如:異步請求,隊列請求,GZIP 壓縮,緩存,斷點續(xù)傳,進度跟蹤,上傳文件,HTTP 認證。在新的版本中,還加入了 Objective-C 閉包 Block 的支持,讓我們的代碼加輕簡靈活。
下面就舉例說明它的 API 用法。
發(fā)起一個同步請求
同步意為著線程阻塞,在主線程中使用此方法會使應(yīng)用Hang住而不響應(yīng)任何用戶事件。所以,在應(yīng)用程序設(shè)計時,大多被用在專門的子線程增加用戶體驗,或用異步請求代替(下面會講到)。
- - (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 方法啟動同步訪問
由于是同步請求,沒有基于事件的回調(diào)方法,所以從 request的error 屬性獲取錯誤信息
responseString,為請求的返回 NSString 信息
創(chuàng)建一個異步請求
異步請求的好處是不阻塞當前線程,但相對于同步請求略為復雜,至少要添加兩個回調(diào)方法來獲取異步事件。下面異步請求代碼完成上面同樣的一件事情:
- - (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
 - NSData *responseData = [request responseData];
 - }
 - - (void)requestFailed:(ASIHTTPRequest *)request
 - {
 - NSError *error = [request error];
 - }
 
與上面不同的地方是指定了一個 "delegate",并用 startAsynchronous 來啟動網(wǎng)絡(luò)請求
在這里實現(xiàn)了兩個 delegate 的方法,當數(shù)據(jù)請求成功時會調(diào)用 requestFinished,請求失敗時(如網(wǎng)絡(luò)問題或服務(wù)器內(nèi)部錯誤)會調(diào)用 requestFailed。
隊列請求
提供了一個對異步請求更加精準豐富的控制。如:可以設(shè)置在隊列中同步請求的連接數(shù)。往隊列里添加的請求實例數(shù)大于 maxConcurrentOperationCount 時,請求實例將被置為等待,直到前面至少有一個請求完成并出列才被放到隊列里執(zhí)行。這也適用于當我們有多個請求需求按順序執(zhí)行的時候(可能是業(yè)務(wù)上的需要,也可能是軟件上的調(diào)優(yōu)),僅僅需要把 maxConcurrentOperationCount 設(shè)為“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];
 - }
 
創(chuàng)建 NSOperationQueue,這個 Cocoa 架構(gòu)的執(zhí)行任務(wù)(NSOperation)的任務(wù)隊列。我們通過 ASIHTTPRequest.h 的源碼可以看到,此類本身就是一個 NSOperation 的子類。也就是說它可以直接被放到"任務(wù)隊列"中并被執(zhí)行。上面的代碼除了隊列的創(chuàng)建與添加操作外,其它代碼與上一例一樣。
隊列異步請求中中獲取或識別不同request小技巧
可以設(shè)置一個上下文(userInfo)到 request 對象中,當請求響應(yīng)完后可以通過訪問 request 對象的 userInfo 獲取里面的信息
為每一個請求實例設(shè)置不同的 setDidFinishSelector / setDidFailSelector 的回調(diào)方法
子類化 ASIHTTPRequest,重寫 requestFinished: 與 failWithProblem: 方法
ASINetworkQueues, 它的delegate提供更為豐富的功能
提供的更多的回調(diào)方法如下:
- requestDidStartSelector,請求發(fā)起時會調(diào)此方法,你可以在此方法中跟據(jù)業(yè)務(wù)選擇性的設(shè)置 request 對象的 deleaget
 - requestDidReceiveResponseHeadersSelector,當接受完響應(yīng)的 Header 后設(shè)計此方法,這個對下載大數(shù)據(jù)的時候相當有用,你可以在方法里做更多業(yè)務(wù)上的處理
 - requestDidFinishSelector,請求并響應(yīng)成功完成時調(diào)用此方法
 - requestDidFailSelector,請求失敗
 - queueDidFinishSelector,整個隊列里的所有請求都結(jié)束時調(diào)用此方法
 
它是 NSOperationQueues 的擴展,小而強大。但也與它的父類略有區(qū)別。如,僅添加到隊列中其實并不能執(zhí)行請求,只有調(diào)用[ queue g o ]才會執(zhí)行;一個正在運行中的隊列,并不需要重復調(diào)用[ queue go ]。默認情況下,隊列中的一個請求如果失敗,它會取消所有未完成的請求??梢栽O(shè)置[ queue setShouldCancelAllRequestsOnFailure:NO ]來修正。
取消異步請求
首先,同步請求是不能取消的。
其次,不管是隊列請求,還是簡單的異步請求,全部調(diào)用[ request cancel ]來取消請求。取消的請求默認都會按請求失敗處理,并調(diào)用請求失敗delegate。
如果不想調(diào)用delegate方法,則設(shè)置:[ request clearDelegatesAndCancel];
隊列請求中需要注意的是,如果你取消了一個請求,隊列會自動取消其它所有請求。如果只想取消一個請求,可以設(shè)置隊列:
- [ queue setShouldCancelAllRequestsOnFailure:NO ];
 
如果想明確取消所有請求:[ queue cancelAllOperations ];
安全的內(nèi)存回收建議
request并沒有retain你的delegate,所以在沒有請求完的時候釋放了此delegate,需要在dealloc方法里先取消所有請求,再釋放請求實例,如:
- - (void)dealloc
 - {
 - [request clearDelegatesAndCancel];
 - [request release];
 - ...
 - [super dealloc];
 - }
 
向服務(wù)器端上傳數(shù)據(jù)
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"];
 
如果要發(fā)送自定義數(shù)據(jù):
- 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"];
 
下載文件
通過設(shè)置request的setDownloadDestinationPath,可以設(shè)置下載文件用的下載目標目錄。
首先,下載過程文件會保存在temporaryFileDownloadPath目錄下。如果下載完成會做以下事情:
如果數(shù)據(jù)是壓縮的,進行解壓,并把文件放在 downloadDestinationPath 目錄中,臨時文件被刪除 
如果下載失敗,臨時文件被直接移到 downloadDestinationPath 目錄,并替換同名文件
如果你想獲取下載中的所有數(shù)據(jù),可以實現(xiàn) delegate 中的 request:didReceiveData:方法。但如果你實現(xiàn)了這個方法,request 在下載完后,request 并不把文件放在 downloadDestinationPath 中,需要手工處理。
獲取響應(yīng)信息
信息:status , header, responseEncoding
- [request responseStatusCode];
 - [[request responseHeaders] objectForKey:@"X-Powered-By"];
 - [request responseEncoding];
 
獲取請求進度
有兩個回調(diào)方法可以獲取請求進度:
- 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]);
 
大文件斷點續(xù)傳0.94 以后支持大文件的斷點下載,只需要設(shè)置
- [ request setAllowResumeForFileDownloads:YES ];
 - [ request setDownloadDestinationPath:downloadPath ];
 
就可以了。
小結(jié):iPhone應(yīng)用開發(fā)中ASIHTTPRequest詳解的內(nèi)容介紹完了,希望通過本文的學習能對你有所幫助!















 
 
 
 
 
 
 