以下內容為原創,歡迎轉載,轉載請注明
來自天天博客:http://www.cnblogs.com/tiantianbyconan/p/3409721.html
一般情況下的POST異步操作需要實現以下幾步:
1. 在controller.h上實現<NSURLConnectionDataDelegate>協議
2. 實現協議的幾個方法,
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
3. 編寫執行post請求的代碼:
1 NSURL *url = [NSURL URLWithString:urlStr]; // 生成NSURL對象 2 // 生成Request請求對象(並設置它的緩存協議、網絡請求超時配置) 3 NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:url cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:30]; 4 5 [request setHTTPBody:[params dataUsingEncoding:NSUTF8StringEncoding]]; // 設置請求參數 6 7 // 執行請求連接 8 NSURLConnection *conn = [[NSURLConnection alloc] initWithRequest:request delegate:executorDelegate];
如果controller有很多異步操作,處理就會很麻煩,而且,很多時候我們只需要處理完成和異常(比如超時)的時候的反饋即可
所以,我需要編寫一個post請求的封裝類,只要傳入請求的url、請求參數(字符串形式)、完成時的回調block
首先,新建類:HttpPostExecutor,.h如下:
1 // 2 // HttpPostExecutor.h 3 // HttpTest 4 // 5 // Created by WANGJIE on 13-11-6. 6 // Copyright (c) 2013年 WANGJIE. All rights reserved. 7 // 8 9 #import <Foundation/Foundation.h> 10 11 @interface HttpPostExecutor : NSObject<NSURLConnectionDataDelegate> 12 { 13 NSMutableData *resultData; // 存放請求結果 14 void (^finishCallbackBlock)(NSString *); // 執行完成后回調的block 15 16 } 17 @property NSMutableData *resultData; 18 @property(strong) void (^finishCallbackBlock)(NSString *); 19 20 + (void)postExecuteWithUrlStr:(NSString *)urlStr Paramters:(NSString *)params FinishCallbackBlock:(void (^)(NSString *))block; 21 22 @end
實現了<NSURLConnectionDataDelegate>協議,因為它要接收post請求的幾個回調。
有一個NSMutableData對象,這個對象用於儲存請求的結果。
一個finishCallbackBlock的block,這個block用於執行完成后的回調,這個block傳入的參數就是返回的結果(這個結果已轉成utf-8編碼的字符串形式),我們可以在這個block中去處理請求完成后的邏輯
還有一個類方法,這個類方法暴露給外面,讓外面進行調用
接下來,我們看下實現的方法.m文件:

1 // 2 // POST異步請求的封裝 3 // 使用方法,只需傳入url,參數組成的字符串,執行完成后的回調block 4 // 如下: 5 // [HttpPostExecutor postExecuteWithUrlStr:@"http://www.baidu.com" 6 // Paramters:@"" 7 // FinishCallbackBlock:^(NSString *result){ // 設置執行完成的回調block 8 // NSLog(@"finish callback block, result: %@", result); 9 // }]; 10 // post提交的參數,格式如下: 11 // 參數1名字=參數1數據&參數2名字=參數2數據&參數3名字=參數3數據&... 12 // 13 // 14 // HttpPostExecutor.m 15 // HttpTest 16 // 17 // Created by WANGJIE on 13-11-6. 18 // Copyright (c) 2013年 WANGJIE. All rights reserved. 19 // 20 21 #import "HttpPostExecutor.h" 22 23 @implementation HttpPostExecutor 24 @synthesize resultData, finishCallbackBlock; 25 26 /** 27 * 執行POST請求 28 */ 29 + (void)postExecuteWithUrlStr:(NSString *)urlStr Paramters:(NSString *)params FinishCallbackBlock:(void (^)(NSString *))block 30 { 31 // 生成一個post請求回調委托對象(實現了<NSURLConnectionDataDelegate>協議) 32 HttpPostExecutor *executorDelegate = [[HttpPostExecutor alloc] init]; 33 executorDelegate.finishCallbackBlock = block; // 綁定執行完成時的block 34 35 36 NSURL *url = [NSURL URLWithString:urlStr]; // 生成NSURL對象 37 // 生成Request請求對象(並設置它的緩存協議、網絡請求超時配置) 38 NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:url cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:30]; 39 40 [request setHTTPBody:[params dataUsingEncoding:NSUTF8StringEncoding]]; // 設置請求參數 41 42 // 執行請求連接 43 NSURLConnection *conn = [[NSURLConnection alloc] initWithRequest:request delegate:executorDelegate]; 44 45 NSLog(conn ? @"連接創建成功" : @"連接創建失敗"); 46 47 } 48 49 50 /** 51 * 接收到服務器回應的時回調 52 */ 53 - (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response 54 { 55 NSHTTPURLResponse *resp = (NSHTTPURLResponse *)response; 56 // 初始化NSMutableData對象(用於保存執行結果) 57 if(!resultData){ 58 resultData = [[NSMutableData alloc] init]; 59 }else{ 60 [resultData setLength:0]; 61 } 62 63 if ([response respondsToSelector:@selector(allHeaderFields)]) { 64 65 NSDictionary *dictionary = [resp allHeaderFields]; 66 67 NSLog(@"[network]allHeaderFields:%@",[dictionary description]); 68 } 69 70 } 71 /** 72 * 接收到服務器傳輸數據的時候調用,此方法根據數據大小執行若干次 73 */ 74 - (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data 75 { 76 [resultData appendData:data]; // 追加結果 77 } 78 /** 79 * 數據傳完之后調用此方法 80 */ 81 - (void)connectionDidFinishLoading:(NSURLConnection *)connection 82 { 83 // 把請求結果以UTF-8編碼轉換成字符串 84 NSString *resultStr = [[NSString alloc] initWithData:[self resultData] encoding:NSUTF8StringEncoding]; 85 86 if (finishCallbackBlock) { // 如果設置了回調的block,直接調用 87 finishCallbackBlock(resultStr); 88 } 89 90 91 } 92 /** 93 * 網絡請求過程中,出現任何錯誤(斷網,連接超時等)會進入此方法 94 */ 95 - (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error 96 { 97 NSLog(@"network error: %@", [error localizedDescription]); 98 99 if (finishCallbackBlock) { // 如果設置了回調的block,直接調用 100 finishCallbackBlock(nil); 101 } 102 103 104 } 105 @end
在這個實現類中,我們在類方法中,先生成一個HttpPostExecutor對象,這個對象用於post請求的回調(因為實現了<NSURLConnectionDataDelegate>協議),然后去執行post連接。
接下來就等下面實現的回調方法被自動調用了,一旦調用
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
這個方法,就對resultData(用於存儲post請求結果)進行初始化或者清空,因為要開始真正存儲數據了嘛;
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
這個方法進行回調的時候,把返回過來的這部分數據存儲到resultData中,沒什么好說的;
一旦回調- (void)connectionDidFinishLoading:(NSURLConnection *)connection這個方法,說明數據傳輸完畢了,要做的邏輯就是把數據轉成utf-8編碼的字符串,然后回調我們設置的回調finishCallbackBlock,把轉好的結果字符串傳進去,這樣我們在回調block方法中實現的邏輯就能正常執行了。
一旦回調- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error這個方法,說明請求過程中出錯了,比如斷電、超時等,這時候,也回調我們設置的回調finishCallbackBlock,nil作為結果,這樣我們在finishCallbackBlock中就能判斷是正常的執行了post還是出了問題。
好了,接下來,我們就可以在外面去調用了,如下:
1 [HttpPostExecutor postExecuteWithUrlStr:@"http://www.baidu.com" 2 Paramters:@"" 3 FinishCallbackBlock:^(NSString *result){ 4 // 執行post請求完成后的邏輯 5 NSLog(@"finish callback block, result: %@", result); 6 }];
這樣,以后post請求只需要去調用上面這個方法,在回調block中去處理結果
之后,在我們的代碼編寫中,就可以只關心業務邏輯,不需要去在意請求協議和回調了