zoukankan      html  css  js  c++  java
  • 【ios】使用Block对POST异步操作的简单封装

    以下内容为原创,欢迎转载,转载请注明

    来自天天博客: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中去处理结果

    之后,在我们的代码编写中,就可以只关心业务逻辑,不需要去在意请求协议和回调了

    测试demo下载

  • 相关阅读:
    AC自动机【学习笔记】
    SCOI2016 背单词【Trie树,贪心】
    【字符串算法】字典树Trie入门
    USACO 1.3 Name That Number【暴搜】
    MapReduce分组
    MapReduce排序
    博客园添加访问人数统计
    MapReduce的分区
    MapReduce的计数器
    MapReduce部分源码解读(一)
  • 原文地址:https://www.cnblogs.com/tiantianbyconan/p/3409721.html
Copyright © 2011-2022 走看看