使用Block对POST异步操作的简单封装,NSURLConnection
2014-03-28 15:44
429 查看
对于网络请求有很多方法,也有很多第三方的,ASI ,AFNetworking等,最近想自己写一个简单的封装!一开始我用的是代理来进行回调,这样也是可以的;后来看到很多博客用过的block来做回调,下面是借鉴别人的写的!
一般情况下的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请求的代码:
如果controller有很多异步操作,处理就会很麻烦,而且,很多时候我们只需要处理完成和异常(比如超时)的时候的反馈即可
所以,我需要编写一个post请求的封装类,只要传入请求的url、请求参数(字符串形式)、完成时的回调block
首先,新建类:HttpPost,.h如下:
实现了<NSURLConnectionDataDelegate>协议,因为它要接收post请求的几个回调。
有一个NSMutableData对象,这个对象用于储存请求的结果。
一个finishCallbackBlock的block,这个block用于执行完成后的回调,这个block传入的参数就是返回的结果(这个结果已转成utf-8编码的字符串形式),我们可以在这个block中去处理请求完成后的逻辑
还有一个类方法,这个类方法暴露给外面,让外面进行调用
在这个实现类中,我们在类方法中,先生成一个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还是出了问题。
接下来,我们就可以在外面去调用了,如下:
以后post请求只需要去调用上面这个方法,在回调block中去处理结果。
其实,这个还可以继续封装,把URL和FinishCallback分开,这样看起来会调理清晰点,因为大部分人写代码喜欢条条框框的列出来感觉明显清晰;如果觉得block不好理解或者不习惯,直接把block那部分去掉,加上自己的代理,把返回数据通过代理传出来也是一样的!
一般情况下的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请求的代码:
NSURL *url = [NSURL URLWithString:urlStr]; // 生成NSURL对象 // 生成Request请求对象(并设置它的缓存协议、网络请求超时配置) NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:url cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:30]; [request setHTTPBody:[params dataUsingEncoding:NSUTF8StringEncoding]]; // 设置请求参数 // 执行请求连接 NSURLConnection *conn = [[NSURLConnection alloc] initWithRequest:request delegate:executorDelegate];
如果controller有很多异步操作,处理就会很麻烦,而且,很多时候我们只需要处理完成和异常(比如超时)的时候的反馈即可
所以,我需要编写一个post请求的封装类,只要传入请求的url、请求参数(字符串形式)、完成时的回调block
首先,新建类:HttpPost,.h如下:
#import <Foundation/Foundation.h> @interface HttpPost : NSObject<NSURLConnectionDataDelegate> { NSMutableData *resultData; // 存放请求结果 void (^finishCallbackBlock)(NSString *); // 执行完成后回调的block } @property NSMutableData *resultData; @property(strong) void (^finishCallbackBlock)(NSString *); + (void)postExecuteWithUrlStr:(NSString *)urlStr Paramters:(NSString *)params FinishCallbackBlock:(void (^)(NSString *))block;
实现了<NSURLConnectionDataDelegate>协议,因为它要接收post请求的几个回调。
有一个NSMutableData对象,这个对象用于储存请求的结果。
一个finishCallbackBlock的block,这个block用于执行完成后的回调,这个block传入的参数就是返回的结果(这个结果已转成utf-8编码的字符串形式),我们可以在这个block中去处理请求完成后的逻辑
还有一个类方法,这个类方法暴露给外面,让外面进行调用
#import "HttpPost.h"
@implementation HttpPost
@synthesize resultData, finishCallbackBlock;
/**
* 执行POST请求
*/
+ (void)postExecuteWithUrlStr:(NSString *)urlStr Paramters:(NSString *)params FinishCallbackBlock:(void (^)(NSString *))block
{
// 生成一个post请求回调委托对象(实现了<NSURLConnectionDataDelegate>协议)
HttpPostExecutor *executorDelegate = [[HttpPostExecutor alloc] init];
executorDelegate.finishCallbackBlock = block; // 绑定执行完成时的block
NSURL *url = [NSURL URLWithString:urlStr]; // 生成NSURL对象 // 生成Request请求对象(并设置它的缓存协议、网络请求超时配置) NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:url cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:30]; [request setHTTPBody:[params dataUsingEncoding:NSUTF8StringEncoding]]; // 设置请求参数 // 执行请求连接 NSURLConnection *conn = [[NSURLConnection alloc] initWithRequest:request delegate:executorDelegate];
NSLog(conn ? @"连接创建成功" : @"连接创建失败");
}
/**
* 接收到服务器回应的时回调
*/
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
NSHTTPURLResponse *resp = (NSHTTPURLResponse *)response;
// 初始化NSMutableData对象(用于保存执行结果)
if(!resultData){
resultData = [[NSMutableData alloc] init];
}else{
[resultData setLength:0];
}
if ([response respondsToSelector:@selector(allHeaderFields)]) {
NSDictionary *dictionary = [resp allHeaderFields];
NSLog(@"[network]allHeaderFields:%@",[dictionary description]);
}
}
/**
* 接收到服务器传输数据的时候调用,此方法根据数据大小执行若干次
*/
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
[resultData appendData:data]; // 追加结果
}
/**
* 数据传完之后调用此方法
*/
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
// 把请求结果以UTF-8编码转换成字符串
NSString *resultStr = [[NSString alloc] initWithData:[self resultData] encoding:NSUTF8StringEncoding];
if (finishCallbackBlock) { // 如果设置了回调的block,直接调用
finishCallbackBlock(resultStr);
}
}
/**
* 网络请求过程中,出现任何错误(断网,连接超时等)会进入此方法
*/
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
NSLog(@"network error: %@", [error localizedDescription]);
if (finishCallbackBlock) { // 如果设置了回调的block,直接调用
finishCallbackBlock(nil);
}
}
@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还是出了问题。
接下来,我们就可以在外面去调用了,如下:
[HttpPost postExecuteWithUrlStr:@"http://www.baidu.com" Paramters:@"" FinishCallbackBlock:^(NSString *result){ // 执行post请求完成后的逻辑 NSLog(@"finish callback block, result: %@", result); }];
以后post请求只需要去调用上面这个方法,在回调block中去处理结果。
其实,这个还可以继续封装,把URL和FinishCallback分开,这样看起来会调理清晰点,因为大部分人写代码喜欢条条框框的列出来感觉明显清晰;如果觉得block不好理解或者不习惯,直接把block那部分去掉,加上自己的代理,把返回数据通过代理传出来也是一样的!
相关文章推荐
- 【ios】使用Block对POST异步操作的简单封装
- 对于Android中Thread异步操作中post方法内使用Toast
- Retrofit简单封装使用--Post请求封装请求体、Get请求通过参数、map方式构建url
- 对AFNetworking简单封装GET,POST请求(block方法)
- 【Android】Retrofit的使用(4)-Retrofit进行简单的GET和POST访问操作
- Realm的简单使用(单表_增删改查_包含异步操作)
- C#实现多级子目录Zip压缩解压实例 NET4.6下的UTC时间转换 [译]ASP.NET Core Web API 中使用Oracle数据库和Dapper看这篇就够了 asp.Net Core免费开源分布式异常日志收集框架Exceptionless安装配置以及简单使用图文教程 asp.net core异步进行新增操作并且需要判断某些字段是否重复的三种解决方案 .NET Core开发日志
- 简单的 TouchID demo 的使用 && UIlaterView block的封装 && UIAlertController使用.block的回调
- Android使用异步的误区(关于Handler.post的操作方式)
- Guava Cache内存缓存使用实践-定时异步刷新及简单抽象封装
- okttp的get异步和同步 post的异步简单使用情况
- Guava Cache内存缓存使用实践-定时异步刷新及简单抽象封装
- iOS 网络开发NSURLConnection——使用block回调方法发送异步请求
- 使用基于Android网络通信的OkHttp库实现Get和Post方式简单操作服务器JSON格式数据
- RxJava2+retrofit简单使用,基于POST请求封装工具类
- redis学习之Jedis使用线程池封装redis的基本操作及spring的简单封装
- Guava Cache内存缓存使用实践-定时异步刷新及简单抽象封装
- Jersey使用总结一(jersey初步使用和简单post请求几种参数传递,String方式,不含对象操作)
- iOS简单封装网络请求,使用block回掉函数方式
- IOS网络篇10之NSURLConnection的使用(同步异步下载getpost)