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