ASIHTTPRequest是一款極其強勁的HTTP通路開源項目。讓簡單的API完成複雜的功能,
如:異步請求,隊列請求,GZIP壓縮,緩存,斷點續傳,進度跟蹤,上傳檔案,HTTP認證在新的版本中,還加入了Objective-C閉包Block的支援,讓我們的代碼更加輕簡靈活。
下面就舉例說明它的API用法。
同步意為着線程阻塞,在主線程中使用此方法會使應用Hang住而不響應任何使用者事件。是以,在應用程式設計時,大多被用在專門的子線程增加使用者體驗,或用異步請求代替(下面會講到)。
- (IBAction)grabURL:(id)sender
{
NSURL *url = [NSURL URLWithString:@"http://allseeing-i.com"];
ASIHTTPRequest *request = [ASIHTTPRequestrequestWithURL:url];
[request startSynchronous];NSError *error = [request error];if (!error) {
NSString *response = [request responseString];}
}
a, 用requestWithURL快捷方法擷取ASIHTTPRequest的一個執行個體
b, startSynchronous 方法啟動同步通路,
c, 由于是同步請求,沒有基于事件的回調方法,是以從request的error屬性擷取錯誤資訊。
d, responseString,為請求的傳回NSString資訊。
異步請求的好處是不阻塞目前線程,但相對于同步請求略為複雜,至少要添加兩個回調方法來擷取異步事件。下面異步請求代碼完成上面同樣的一件事情:
- (IBAction)grabURLInBackground:(id)sender
{
NSURL *url = [NSURL URLWithString:@"http://allseeing-i.com"];
ASIHTTPRequest *request = [ASIHTTPRequestrequestWithURL: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];}
a,與上面不同的地方是指定了一個 “delegate”,并用startAsynchronous來啟動網絡請求。b,在這裡實作了兩個delegate的方法,當資料請求成功時會調用requestFinished,請求失敗時(如網絡問題或伺服器内部錯誤)會調用requestFailed。
提供了一個對異步請求更加精準豐富的控制。如,可以設定在隊列中,同步請求的連接配接數。往隊列裡添加的請求執行個體數大于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 = [ASIHTTPRequestrequestWithURL:url];
[request setDelegate:self];
[request setDidFinishSelector:@selector(requestDone:)];
[request setDidFailSelector:@selector(requestWentWrong:)];
[[self queue] addOperation:request]; //queue is anNSOperationQueue
}
-
- (void)requestDone:(ASIHTTPRequest *)request{
NSString *response = [request responseString];}
-
- (void)requestWentWrong:(ASIHTTPRequest *)request{
NSError *error = [request error];}
建立NSOperationQueue,這個Cocoa架構的執行任務(NSOperation)的任務隊列。我們通過ASIHTTPRequest.h的源碼可以看到,此類本身就是一個NSOperation的子類。也就是說它可以直接被放到”任務隊列”中,并被執行。上面的代碼隊了隊列的建立與添加操作外,其它代碼與上一例一樣。a,可以設定一個上下文(userInfo)到request對象中,當請求響應完後可以通過通路request對象的userInfo擷取裡面的資訊b,為每一個請求執行個體設定不同的setDidFinishSelector / setDidFailSelector
的回調方法
c,子類化ASIHTTPRequest,重寫requestFinished: 與 failWithProblem:方法
ASINetworkQueues, delegate提供的更多的回調方法如下:a,requestDidStartSelector,請求發起時會調此方法,你可以在此方法中跟據業務選擇性的設定request對象的deleaget。b,requestDidReceiveResponseHeadersSelector,當接受完響應的Header後設計此方法,這個對下載下傳大資料的時候相當有用,你可以在方法裡做更多業務上的處理。c,requestDidFinishSelector,請求并響應成功完成時調用此方法d,requestDidFailSelector,請求失敗e,queueDidFinishSelector,整個隊列裡的所有請求都結束時調用此方法。
它是NSOperationQueues的擴充,小而強大。但也與它的父類略有差別。如,僅添加到隊列中其實并不能執行請求,隻有調用[ queue g o]才會執行;一個正在運作中的隊列,并不需要重複調用[ queue go ]。預設情況下,隊列中的一個請求如果失敗,它會取消所有未完成的請求。可以設定[ queuesetShouldCancelAllRequestsOnFailure:NO ]來修 正。
首先,同步請求是不能取消的。其次,不管是隊列請求,還是簡單的異步請求,全部調用[ request cancel ]來取消請求。
取消的請求預設都會按請求失敗處理,并調用請求失敗delegate。
如果不想調用delegate方法,則設定:[ request clearDelegatesAndCancel];隊列請求中需要注意的是,如果你取消了一個請求,隊列會自動取消其它所有請求。
如果隻想取消一個請求,可以設定隊列:[ queuesetShouldCancelAllRequestsOnFailure: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 = [ASIFormDataRequestrequestWithURL: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 = [ASIHTTPRequestrequestWithURL:url];
[request appendPostData:[@"This is my data"dataUsingEncoding:NSUTF8StringEncoding]];
// Default becomes POST when you use appendPostData: /appendPostDataFromFile: / setPostBody:
[request setRequestMethod:@"PUT"];
通過設定request的setDownloadDestinationPath,可以設定下載下傳檔案用的下
載目标目錄。首先,下載下傳過程檔案會儲存在temporaryFileDownloadPath目錄下。如果下載下傳完成會做以下事情:1,如果資料是壓縮的,進行解壓,并把檔案放在downloadDestinationPath目錄中,臨時檔案被删除2,如果下載下傳失敗,臨時檔案被直接移到downloadDestinationPath目錄,并替換同名檔案。
如果你想擷取下載下傳中的所有資料,可以實作delegate中的request:didReceiveData:方法。但如果你實作了這個方法,request在下載下傳完後,request并不把檔案放在downloadDestinationPath中,需要手工處理。
資訊:status , header, responseEncoding
[request responseStatusCode];
[[request responseHeaders] objectForKey:@"X-Powered-By"];
[request responseEncoding];
有兩個回調方法可以擷取請求進度,1,downloadProgressDelegate,可以擷取下載下傳進度2,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:[NSDatedateWithTimeIntervalSinceNow: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:[NSMutableArrayarrayWithObject: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 ];
就可以了。ASIHTTPRequest會自動儲存通路過的URL資訊,并備之後用。在以下幾個場景非常有用:
1,當沒有網絡連接配接的時候。2,已下載下傳的資料再次請求時,僅當它與本地版本不樣時才進行下載下傳。ASIDownloadCache 它對Get請求的響應資料進行緩存(被緩存的資料必需是成功的200請求):
[ASIHTTPRequest setDefaultCache:[ASIDownloadCachesharedCache]];當設定緩存政策後,所有的請求都被自動的緩存起來。另外,如果僅僅希望某次請求使用緩存操作,也可以這樣使用:ASIHTTPRequest *request = [ASIHTTPRequestrequestWithURL:url];
[request setDownloadCache:[ASIDownloadCachesharedCache]];
僅僅需要建立不同的ASIDownloadCache,并設定緩存所使用的路徑,并設定到需要使用的request執行個體中:
ASIDownloadCache *cache = [[[ASIDownloadCache alloc]init] autorelease];
[cache setStoragePath:@"/Users/ben/Documents/Cached-Downloads"];
[self setMyCache:cache];
ASIHTTPRequest *request = [ASIHTTPRequestrequestWithURL:url];
[request setDownloadCache:[self myCache]];
緩存政策是我們控制緩存行為的主要方式,如:什麼時候進行緩存,緩存資料的利用方式。
以下是政策可選清單(可組合使用):
ASIUseDefaultCachePolicy
ASIDoNotReadFromCacheCachePolicy
這是一個預設的緩存政策“ASIAskServerIfModifiedWhenStaleCachePolicy”,這個很明白,見名知意(它不能與其它政策組合使用)
所讀資料不使用緩存ASIDoNotWriteToCacheCachePolicy 不對緩存資料進行寫操作
預設緩存行為,request會先判斷是否存在緩存資料。a, 如果沒有再進行網絡請求。b,如果存在緩存資料,并且資料沒有過
ASIAskServerIfModifiedWhenStaleC 期,則使用緩存。c,如果存在緩存資料,achePolicy 但已經過期,request會先進行網絡請求,
判斷伺服器版本與本地版本是否一樣,如果 一樣,則使用緩存。如果伺服器有新版本,
能與其它政策組合使用)
ASIDoNotReadFromCacheCachePolicy
所讀資料不使用緩存ASIDoNotWriteToCacheCachePolicy 不對緩存資料進行寫操作
ASIAskServerIfModifiedWhenStaleCachePolicy
ASIAskServerIfModifiedCachePolicyASIOnlyLoadIfNotCachedCachePolicy
ASIDontLoadCachePolicy
ASIFallbackToCacheIfLoadFailsCachePolicy
預設緩存行為,request會先判斷是否存在緩存資料。a, 如果沒有再進行網絡請求。b,如果存在緩存資料,并且資料沒有過期,則使用緩存。c,如果存在緩存資料,但已經過期,request會先進行網絡請求,判斷伺服器版本與本地版本是否一樣,如果一樣,則使用緩存。如果伺服器有新版本,會進行網絡請求,并更新本地緩存與預設緩存大緻一樣,差別僅是每次請求都會 去伺服器判斷是否有更新
如果有緩存在本地,不管其過期與否,總會
拿來使用
僅當有緩存的時候才會被正确執行,如果沒有緩存,request将被取消(沒有錯誤資訊)這個選項經常被用來與其它選項組合使用。請求失敗時,如果有緩存當網絡則傳回本地緩存資訊(這個在處理異常時非常有用)
如果設定了“defaultCachePolicy”則所有的請求都會使用此緩存。
你可以設定緩存的資料需要儲存多長時間,ASIHTTPRequest提供了兩種政策:a,ASICacheForSessionDurationCacheStoragePolicy,預設政策,基于session的緩存資料存儲。當下次運作或[ASIHTTPRequest clearSession]時,緩存将失效。b,ASICachePermanentlyCacheStoragePolicy,把緩存資料永久儲存在本地,
如:
ASIHTTPRequest *request = [ ASIHTTPRequestrequestWithURL:url ];
[ request
setCacheStoragePolicy:ASICachePermanentlyCacheStoragePolicy ];另外,也可以使用clearCachedResponsesForStoragePolicy來清空指定政策下的緩存資料。
設定是否按伺服器在Header裡指定的是否可被緩存或過期政策進行緩存:[[ ASIDownloadCache sharedCache ]setShouldRespectCacheControlHeaders:NO ];設定request緩存的有效時間:
[ request setSecondsToCache:60*60*24*30 ]; // 緩存30天可以判斷資料是否從緩存讀取:
[ request didUseCachedResponse ];
設定緩存所使用的路徑:
[ request setDownloadDestinationPath:[[ ASIDownloadCachesharedCache ]pathToStoreCachedResponseDataForRequest:request ]];隻要簡單的實作ASICacheDelegate接口就可以被用來使用。
預設的情況下,ASIHTTPRequest會使用被設定的預設代理。但你也可以手動修改http代理:
// Configure a proxy server manually
NSURL *url = [ NSURL URLWithString:@"http://allseeing-i.com/ignore" ];
ASIHTTPRequest *request = [ ASIHTTPRequestrequestWithURL:url ];
[ request setProxyHost:@"192.168.0.1" ];[ request setProxyPort:3128 ];
// Alternatively, you can use a manually-specified ProxyAuto Config file (PAC)
// (It's probably best if you use a local file)[request setPACurl:[NSURL URLWithString:@"file:///Users/
ben/Desktop/test.pac"]];
ASIHTTPRequest,iOS4中,當應用背景運作時仍然請求資料:
[ requestsetShouldContinueWhenAppEntersBackground:YES ];是否有網絡請求:
[ ASIHTTPRequest isNetworkInUse ]是否顯示網絡請求資訊在status bar上:
[ ASIHTTPRequestsetShouldUpdateNetworkActivityIndicator:NO ];設定請求逾時時,設定重試的次數:
[ request setNumberOfTimesToRetryOnTimeout:2 ];KeepAlive的支援:
// Set the amount of time to hang on to a persistentconnection before it should expire to 2 minutes
[ request setPersistentConnectionTimeoutSeconds:120 ];
// Disable persistent connections entirely
[ request setShouldAttemptPersistentConnection:NO ];... other posts by pimacun
每次在工程中添加ASIHttpRequest都記不住要加哪些庫,還是别懶了,好記性不如爛筆頭,寫下來吧。
libz.dylib
SystemConfiguration.framework
CFNetwork.framework
MobileCoreServices.framework
這四個應該就夠了,添加之後,項目可以編譯通過。
SDWebImage需要用到的framework
使用目前GitHub上最新的2.6版本,需要添加
MapKit.framework
ImageIO.framework