標籤:
開發iOS應用要調用Http介面、擷取Http資源,有一套比較成熟的架構ASIHTTPRequest。而我還是比較喜歡使用原始一點的 API,而它跟其他的物件導向語言有許多共通之處。本文分同步請求和非同步請求這兩種情況來講解一下Http API的使用。直接上代碼,注釋即文檔!
同步請求:即發起Http請求、擷取並處理傳回值都在同一個線程中進行
view sourceprint?
01.
//建立URL對象
02.
NSString *urlStr = @
"http://blog.csdn.net/rongxinhua"
;
03.
NSURL *url = [[NSURL alloc] initWithString:urlStr];
04.
05.
//建立HTTP請求
06.
//方法1(註:NSURLRequest只支援Get請求,NSMutableURLRequest可支援Get和Post請求)
07.
NSURLRequest *request = [[NSURLRequest alloc] initWithURL:url];
08.
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:url];
09.
//方法2,使用Factory 方法建立
10.
NSURLRequest *request = [NSURLRequest requestWithURL:url];
11.
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
12.
//同時設定緩衝策略和逾時時間
13.
NSMutableURLRequest *request = [NSURLRequest requestWithURL:url cachePolicy:NSURLRequestReloadIgnoringLocalCacheData timeoutInterval:
15
];
14.
15.
//設定Http頭
16.
NSDictionary *headers = [request allHTTPHeaderFields];
17.
[headers setValue:@
"iOS-Client-ABC"
forKey:@
"User-Agent"
];
18.
19.
//佈建要求方法
20.
[request setHTTPMethod:@
"GET"
];
21.
[request setHTTPMethod:@
"POST"
];
22.
23.
//設定要發送的本文內容(適用於Post請求)
24.
NSString *content = @
"username=stanyung&pass<a href="
http:
//www.it165.net/edu/ebg/" target="_blank" class="keylink">word</a>=123";
25.
NSData *data = [content dataUsingEncoding:NSUTF8StringEncoding];
26.
[request setHTTPBody:data];
27.
28.
//同步執行Http請求,擷取返回資料
29.
NSURLResponse *response;
30.
NSError *error;
31.
NSData *result = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
32.
33.
//返資料轉成字串
34.
NSString *html = [[NSString alloc] initWithData:result encoding:NSUTF8StringEncoding];
35.
36.
//(如果有錯誤)錯誤描述
37.
NSString *errorDesc = [error localizedDescription];
38.
39.
//擷取狀態代碼和HTTP回應標頭資訊
40.
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;
41.
NSInteger statusCode = [httpResponse statusCode];
42.
NSDictionary *responseHeaders = [httpResponse allHeaderFields];
43.
NSString *cookie = [responseHeaders valueForKey:@
"Set-Cookie"
];
註:以上代碼,不要Copy直接執行,只是列舉Http常用方法的調用。
非同步請求:發起HTTP請求在一個線程中,返回結果處理在另一個線程中。相比同步請求,非同步請求不需要等待返回結果,當前程式可以繼續往下執行。在Objective-C中,非同步請求也有兩種實現方式:一種是註冊回調代理,一種是使用回調代碼塊。
a.註冊回調代理的方式:
view sourceprint?
1.
[NSURLConnection connectionWithRequest:request delegate:self];
需要實現NSURLConnectionDataDelegate協議:
view sourceprint?
1.
@interface
HttpDownloadService : NSObject<NSURLConnectionDataDelegate> {
2.
}
實現相關的協議方法:
view sourceprint?
01.
NSMutableData *buff;
//暫存響應的資料
02.
bool finished =
false
;
//讀完完整標記
03.
04.
//收到HTTP響應時調用
05.
-(
void
)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
06.
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse*)response;
07.
NSDictionary *headers = [httpResponse allHeaderFields];
08.
buff = [[NSMutableData alloc] init];
09.
}
10.
11.
//讀取返回資料時調用(可能會執行多次此方法)
12.
-(
void
)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
13.
[buff appendData:data];
14.
}
15.
16.
//讀完資料完成時調用
17.
-(
void
)connectionDidFinishLoading:(NSURLConnection *)connection {
18.
NSString *html = [[NSString alloc] initWithData:buff encoding:NSUTF8StringEncoding];
19.
finished =
true
;
20.
}
通常情況下,資料在網路中傳輸,會受到頻寬等因素的影響,並不會一次情將所有資料返回,你可能分幾次才能接受完整一個HTTP響應報文。因此, (void)connection:(NSURLConnection *)didReceiveData:(NSData *) 這個方法很可能會執行多次。
上例代碼中,使用了NSMutableData來暫存接收到的響應資料片段,每一段並接起來,直到讀取完整。
b.使用回調代碼塊的方式:
view sourceprint?
1.
[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:
2.
^(NSURLResponse *response, NSData *result, NSError *error){
//只會進入一次,方法內部已經實現了Buffer作用
3.
NSString *html = [[NSString alloc] initWithData:result encoding:NSUTF8StringEncoding];
4.
}];
跟NSURLConnectionDataDelegate的回調方法不同,這裡的回調代碼塊只調用一次,它內部已經實現了Buffer的作用,等到資料接收完整後才進入此代碼塊。因此,你在代碼塊中擷取到的result可以直接使用。
備忘1:本文的代碼例子將使用ARC編碼模式,故所建立的對象均沒有顯式調用release()方法回收。
備忘2:若你測試本例子代碼建立的是Command Line Tool工程,在main函數中執行相關代碼,上面兩種非同步執行的情況,你很可能你的程式沒有執行到回調方法或回調代碼塊裡面去,這是因為:在main函 數中,主線程沒有等待阻塞,一下子執行完了,回調代碼所在的子線程可能未執行完或者根本還沒開始執行,就已經因為主線程的結束而結束了。解決這個問題,可 以在調用完非同步方法呼叫後面,加以下代碼:
view sourceprint?
1.
while
(!finished) {
2.
[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
3.
}
而finished變數正是上面兩個非同步HTTP例子中定義是否執行完成的變數。
Objective-C Http常用API 同步請求與非同步請求