ASIHTTPRequest詳解 ASIHTTPRequest
是一款極其強(qiáng)勁的 HTTP 訪問開源項目。讓簡單的 API 完成復(fù)雜的功能,如:異步請求,隊列請求,GZIP 壓縮,緩存,斷點(diǎn)續(xù)傳,進(jìn)度跟蹤,上傳文件,HTTP 認(rèn)證。在新的版本中,還加入了 Objective-C 閉包 Block 的支持,讓我們的代碼加輕簡靈活。
下面就舉例說明它的 API 用法。
發(fā)起一個同步請求
同步意為著線程阻塞,在主線程中使用此方法會使應(yīng)用Hang住而不響應(yīng)任何用戶事件。所以,在應(yīng)用程序設(shè)計時,大多被用在專門的子線程增加用戶體驗,或用異步請求代替(下面會講到)。 1.
- (IBAction)grabURL:(id)sender 2.
{ 3.
NSURL *url = [NSURL
URLWithString:@"http://"]; 4.
ASIHTTPRequest *request =
[ASIHTTPRequest requestWithURL:url]; 5.
[request startSynchronous]; 6.
NSError *error = [request
error]; 7.
if (!error) { 8.
NSString *response
= [request responseString]; 9.
} 10.
}
用 requestWithURL 快捷方法獲取 ASIHTTPRequest 的一個實例 startSynchronous 方法啟動同步訪問 由于是同步請求,沒有基于事件的回調(diào)方法,所以從
request的error 屬性獲取錯誤信息 responseString,為請求的返回 NSString 信息 創(chuàng)建一個異步請求
異步請求的好處是不阻塞當(dāng)前線程,但相對于同步請求略為復(fù)雜,至少要添加兩個回調(diào)方法來獲取異步事件。下面異步請求代碼完成上面同樣的一件事情: 1.
- (IBAction)grabURLInBackground:(id)sender 2.
{ 3.
NSURL *url = [NSURL
URLWithString:@"http://"]; 4.
ASIHTTPRequest *request = [ASIHTTPRequest
requestWithURL:url]; 5.
[request setDelegate:self]; 6.
[request startAsynchronous]; 7.
} 8. 9.
- (void)requestFinished:(ASIHTTPRequest *)request 10.
{ 11.
// Use when fetching text data 12.
NSString *responseString = [request
responseString]; 13. 14.
// Use when fetching binary data 15.
NSData *responseData = [request
responseData]; 16.
} 17. 18.
- (void)requestFailed:(ASIHTTPRequest *)request 19.
{ 20.
NSError *error = [request error]; 21.
}
與上面不同的地方是指定了一個
"delegate",并用 startAsynchronous 來啟動網(wǎng)絡(luò)請求 在這里實現(xiàn)了兩個 delegate 的方法,當(dāng)數(shù)據(jù)請求成功時會調(diào)用 requestFinished,請求失敗時(如網(wǎng)絡(luò)問題或服務(wù)器內(nèi)部錯誤)會調(diào)用
requestFailed。 隊列請求
提供了一個對異步請求更加精準(zhǔn)豐富的控制。如:可以設(shè)置在隊列中同步請求的連接數(shù)。往隊列里添加的請求實例數(shù)大于 maxConcurrentOperationCount 時,請求實例將被置為等待,直到前面至少有一個請求完成并出列才被放到隊列里執(zhí)行。這也適用于當(dāng)我們有多個請求需求按順序執(zhí)行的時候(可能是業(yè)務(wù)上的需要,也可能是軟件上的調(diào)優(yōu)),僅僅需要把 maxConcurrentOperationCount 設(shè)為“1”。 1.
- (IBAction)grabURLInTheBackground:(id)sender 2.
{ 3.
if (![self queue]) { 4.
[self
setQueue:[[[NSOperationQueue alloc] init] autorelease]]; 5.
} 6. 7.
NSURL *url = [NSURL
URLWithString:@"http://"]; 8.
ASIHTTPRequest *request = [ASIHTTPRequest
requestWithURL:url]; 9.
[request setDelegate:self]; 10.
[request
setDidFinishSelector:@selector(requestDone:)]; 11.
[request
setDidFailSelector:@selector(requestWentWrong:)]; 12.
[[self queue] addOperation:request]; //queue
is an NSOperationQueue 13.
} 14. 15.
- (void)requestDone:(ASIHTTPRequest *)request 16.
{ 17.
NSString *response = [request
responseString]; 18.
} 19. 20.
- (void)requestWentWrong:(ASIHTTPRequest *)request 21.
{ 22.
NSError *error = [request error]; 23.
}
創(chuàng)建 NSOperationQueue,這個 Cocoa 架構(gòu)的執(zhí)行任務(wù)(NSOperation)的任務(wù)隊列。我們通過 ASIHTTPRequest.h 的源碼可以看到,此類本身就是一個
NSOperation 的子類。也就是說它可以直接被放到"任務(wù)隊列"中并被執(zhí)行。上面的代碼除了隊列的創(chuàng)建與添加操作外,其它代碼與上一例一樣。
隊列異步請求中中獲取或識別不同request小技巧
可以設(shè)置一個上下文(userInfo)到 request 對象中,當(dāng)請求響應(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,當(dāng)接受完響應(yīng)的 Header 后設(shè)計此方法,這個對下載大數(shù)據(jù)的時候相當(dāng)有用,你可以在方法里做更多業(yè)務(wù)上的處理 requestDidFinishSelector,請求并響應(yīng)成功完成時調(diào)用此方法 requestDidFailSelector,請求失敗 queueDidFinishSelector,整個隊列里的所有請求都結(jié)束時調(diào)用此方法 它是 NSOperationQueues 的擴(kuò)展,小而強(qiáng)大。但也與它的父類略有區(qū)別。如,僅添加到隊列中其實并不能執(zhí)行請求,只有調(diào)用[ queue g o ]才會執(zhí)行;一個正在運(yùn)行中的隊列,并不需要重復(fù)調(diào)用[ queue go ]。默認(rèn)情況下,隊列中的一個請求如果失敗,它會取消所有未完成的請求。可以設(shè)置[ queue
setShouldCancelAllRequestsOnFailure:NO ]來修正。
取消異步請求
首先,同步請求是不能取消的。
其次,不管是隊列請求,還是簡單的異步請求,全部調(diào)用[ request
cancel ]來取消請求。取消的請求默認(rèn)都會按請求失敗處理,并調(diào)用請求失敗delegate。 如果不想調(diào)用delegate方法,則設(shè)置:[ request clearDelegatesAndCancel];
隊列請求中需要注意的是,如果你取消了一個請求,隊列會自動取消其它所有請求。如果只想取消一個請求,可以設(shè)置隊列:[ queue setShouldCancelAllRequestsOnFailure:NO ]; 如果想明確取消所有請求:[ queue cancelAllOperations ];
安全的內(nèi)存回收建議
request并沒有retain你的delegate,所以在沒有請求完的時候釋放了此delegate,需要在dealloc方法里先取消所有請求,再釋放請求實例,如: 1.
- (void)dealloc 2.
{ 3.
[request clearDelegatesAndCancel]; 4.
[request release]; 5.
... 6.
[super dealloc]; 7.
}
向服務(wù)器端上傳數(shù)據(jù)
ASIFormDataRequest ,模擬 Form 表單提交,其提交格式與 Header 會自動識別。
沒有文件:application/x-www-form-urlencoded 有文件:multipart/form-data 1.
ASIFormDataRequest *request = [ASIFormDataRequest
requestWithURL:url]; 2.
[request setPostValue:@"Ben"
forKey:@"first_name"]; 3.
[request setPostValue:@"Copsey"
forKey:@"last_name"]; 4.
[request setFile:@"/Users/ben/Desktop/ben.jpg"
forKey:@"photo"]; 5.
[request addData:imageData
withFileName:@"george.jpg" andContentType:@"image/jpeg"
forKey:@"photos"];
如果要發(fā)送自定義數(shù)據(jù): 1.
ASIHTTPRequest *request = [ASIHTTPRequest
requestWithURL:url]; 2.
[request appendPostData:[@"This is my
data" dataUsingEncoding:NSUTF8StringEncoding]]; 3.
// Default becomes POST when you use
appendPostData: / appendPostDataFromFile: / setPostBody: 4.
[request
setRequestMethod:@"PUT"];
下載文件
通過設(shè)置request的setDownloadDestinationPath,可以設(shè)置下載文件用的下載目標(biāo)目錄。
首先,下載過程文件會保存在temporaryFileDownloadPath目錄下。如果下載完成會做以下事情:
如果數(shù)據(jù)是壓縮的,進(jìn)行解壓,并把文件放在
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];
獲取請求進(jìn)度
有兩個回調(diào)方法可以獲取請求進(jìn)度:
downloadProgressDelegate,可以獲取下載進(jìn)度 uploadProgressDelegate,可以獲取上傳進(jìn)度 cookie的支持
如果 Cookie 存在的話,會把這些信息放在 NSHTTPCookieStorage 容器中共享,并供下次使用。你可以用 [
ASIHTTPRequest setSessionCookies:nil ] ; 清空所有 Cookies。當(dāng)然,你也可以取消默認(rèn)的Cookie策略,而使自定義的Cookie: 1.
//Create a cookie 2.
NSDictionary *properties =
[[[NSMutableDictionary alloc] init] autorelease]; 3.
[properties setValue:[@"Test
Value" encodedCookieValue] forKey:NSHTTPCookieValue]; 4.
[properties
setValue:@"ASIHTTPRequestTestCookie" forKey:NSHTTPCookieName]; 5.
[properties
setValue:@"." forKey:NSHTTPCookieDomain]; 6.
[properties setValue:[NSDate
dateWithTimeIntervalSinceNow:60*60] forKey:NSHTTPCookieExpires]; 7.
[properties
setValue:@"/asi-http-request/tests" forKey:NSHTTPCookiePath]; 8.
NSHTTPCookie *cookie = [[[NSHTTPCookie
alloc] initWithProperties:properties] autorelease]; 9.
10.
//This url will return the value of the
'ASIHTTPRequestTestCookie' cookie 11.
url = [NSURL
URLWithString:@"http:///ASIHTTPRequest/tests/read_cookie"]; 12.
request = [ASIHTTPRequest
requestWithURL:url]; 13.
[request setUseCookiePersistence:NO]; 14.
[request setRequestCookies:[NSMutableArray
arrayWithObject:cookie]]; 15.
[request startSynchronous]; 16.
17.
//Should be: I have 'Test Value' as the
value of 'ASIHTTPRequestTestCookie' 18.
NSLog(@"%@",[request
responseString]);
大文件斷點(diǎn)續(xù)傳
0.94 以后支持大文件的斷點(diǎn)下載,只需要設(shè)置 1.
[ request setAllowResumeForFileDownloads:YES ]; 2. 3.
[ request setDownloadDestinationPath:downloadPath ];
就可以了。
ASIHTTPRequest會自動保存訪問過的URL信息,并備之后用。在以下幾個場景非常有用:?1,當(dāng)沒有網(wǎng)絡(luò)連接的時候。?2,已下載的數(shù)據(jù)再次請求時,僅當(dāng)它與本地版本不樣時才進(jìn)行下載。 ASIDownloadCache 設(shè)置下載緩存 它對Get請求的響應(yīng)數(shù)據(jù)進(jìn)行緩存(被緩存的數(shù)據(jù)必需是成功的200請求):
當(dāng)設(shè)置緩存策略后,所有的請求都被自動的緩存起來。?另外,如果僅僅希望某次請求使用緩存操作,也可以這樣使用:
多種的緩存并存 僅僅需要創(chuàng)建不同的ASIDownloadCache,并設(shè)置緩存所使用的路徑,并設(shè)置到需要使用的request實例中:
緩存策略 緩存策略是我們控制緩存行為的主要方式,如:什么時候進(jìn)行緩存,緩存數(shù)據(jù)的利用方式。?以下是策略可選列表(可組合使用):
緩存存儲方式 你可以設(shè)置緩存的數(shù)據(jù)需要保存多長時間,ASIHTTPRequest提供了兩種策略:?a,ASICacheForSessionDurationCacheStoragePolicy,默認(rèn)策略,基于session的緩存數(shù)據(jù)存儲。當(dāng)下次運(yùn)行或[ASIHTTPRequest
clearSession]時,緩存將失效。?b,ASICachePermanentlyCacheStoragePolicy,把緩存數(shù)據(jù)永久保存在本地,?如:
另外,也可以使用clearCachedResponsesForStoragePolicy來清空指定策略下的緩存數(shù)據(jù)。 緩存其它特性 設(shè)置是否按服務(wù)器在Header里指定的是否可被緩存或過期策略進(jìn)行緩存:
設(shè)置request緩存的有效時間:
可以判斷數(shù)據(jù)是否從緩存讀取:
設(shè)置緩存所使用的路徑:
實現(xiàn)自定義的緩存 只要簡單的實現(xiàn)ASICacheDelegate接口就可以被用來使用。 使用代理請求 默認(rèn)的情況下,ASIHTTPRequest會使用被設(shè)置的默認(rèn)代理。但你也可以手動修改http代理:
ASIHTTPRequest, 請求的其它特性 iOS4中,當(dāng)應(yīng)用后臺運(yùn)行時仍然請求數(shù)據(jù):
是否有網(wǎng)絡(luò)請求:
是否顯示網(wǎng)絡(luò)請求信息在status bar上:
設(shè)置請求超時時,設(shè)置重試的次數(shù):
KeepAlive的支持:
版權(quán)歸旺財勇士所有~轉(zhuǎn)載需聲名~
下面來兩個ASIHTTPRequest的小例子: NSURL *url =
[NSURL URLWithString:@"http://www.baidu.com"];?ASIHTTPRequest
*request = [ASIHTTPRequest requestWithURL:url];?[request start];?NSError *error
= [request error];?if (!error) {? NSString *response =
[request responseString];?}?? 當(dāng)你需要添加更多的請求信息時,如,添加個請求Header:?[request
addRequestHeader:@"name" value:@"Jory lee"];?? 添加Post請求時的健值:?[request setPostValue:@"Ben"
forKey:@"first_name"];?[request setPostValue:@"Copsey"
forKey:@"last_name"];?[request
setFile:@"/Users/ben/Desktop/ben.jpg" forKey:@"photo"];??
設(shè)置HTTP的授權(quán)賬號:?[request
setUsername:@"username"];?[request
setPassword:@"password"];?? 一個異步請求:?- (IBAction)grabURLInBackground:(id)sender?{?NSURL *url
= [NSURL URLWithString:@"http://"];?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];?} ?? 在我們數(shù)據(jù)獲取的過程中,如果數(shù)據(jù)源復(fù)雜,一個請求隊列是必不可少的:?- (IBAction)grabURLInTheBackground:(id)sender?{?if
(![self queue]) {?[self setQueue:[[[NSOperationQueue alloc] init]
autorelease]];?}??NSURL *url = [NSURL
URLWithString:@"http://"];?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];?}
另外大家可以通過下面這個代碼例子,看 ASIHTTP 比傳統(tǒng)的 post 方法的方便之處post用法? NSString *post = @"這里放要傳遞的參數(shù)"; ? NSData
*postData = [post dataUsingEncoding:NSASCIIStringEncoding
allowLossyConversion:YES];
? ? NSString *postLength =
[NSString stringWithFormat:@"%d", [postData length]];
? ? NSMutableURLRequest *request
= [[[NSMutableURLRequest alloc] init] autorelease];
? [request setURL:[NSURL URLWithString:@"請求地址"]]; ? [request
setHTTPMethod:@"POST"]; ? [request
setValue:postLength forHTTPHeaderField:@"Content-Length"];
? //[request addValue:@"gzip"
forHTTPHeaderField:@"Accepts-Encoding"];? [request
setValue:@"application/x-www-form-urlencoded"
forHTTPHeaderField:@"Content-Type"];
? [request setHTTPBody:postData];
?? NSURLConnection *conn=[[NSURLConnection alloc] initWithRequest:request
delegate:self]; ? ? if
(conn) ? {
? receivedbData =
[[NSMutableData data] retain];
? } ? else ? {
? // inform the user that the
download could not be made ? } ??ASIHTTP 方法??NSURL
*url = [NSURL URLWithString:@"請求地址"];?//ASIHTTPRequest
*request = [ASIHTTPRequest requestWithURL:url];?ASIFormDataRequest
*request=[ASIFormDataRequest requestWithURL:url];?[request setPostValue:@"值" forKey:@"參數(shù)1"];?[request setPostValue:@"值" forKey:@"參數(shù)2"];??[request start];?NSError *error = [request
error];?if (!error) {?NSString *response = [request
responseString];?NSLog(response);?}??相比之下,ASIHTTP 的確省了很多代碼。更多信息請訪問官方網(wǎng)站 http:/// 以上內(nèi)容均來自互聯(lián)網(wǎng),本人不對其準(zhǔn)確性和版權(quán)糾紛負(fù)責(zé)。 |
|