以下内容为原创,欢迎转载,转载请注明
来自天天博客: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
View Code
在这个实现类中,我们在类方法中,先生成一个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中去处理结果
之后,在我们的代码编写中,就可以只关心业务逻辑,不需要去在意请求协议和回调了