AFN的二次封装使用

一般情况下,我们的网络请求可能是这样写的

- (void)getActivityWithPage:(NSInteger)pageNum
                       Size:(NSInteger)size
                       Type:(NSInteger)type
                   Latitude:(NSNumber*)latitude
                  Longitude:(NSNumber*)Longitude
                    Success:(SuccessFinishedBlock)success
                   Failture:(FailtureFinishedBlock)failture;

实现部分可能是这样(判断网络状态的我就省略了哈,项目中,是需要加上网络状态判断的)

AFHTTPSessionManager *manager = [[AFHTTPSessionManager alloc] initWithBaseURL:[NSURL URLWithString:baseUrl]];
        manager.requestSerializer.timeoutInterval = 10.f;
        NSMutableDictionary *para = [NSMutableDictionary dictionary];
        //设置需要传递的参数para
        [manager GET:kPEActivity parameters:para progress:^(NSProgress * _Nonnull downloadProgress) {
        } success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
            //这里,大部分就是转成自己的model,可以直接用MJExtension,很方便的
            success(model);//存储数据成功的model
        } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
            NSLog(@"%@",error);
            failture(error);
        }];

不同的页面,会有很多不同的请求,我们就要一个一个去写类似的方法,当然,这样的好处是,通过请求名字,就可以知道是哪个请求,对数据的处理,也有很大的自由度。
一般情况下,如果后台是一个有点经验的,返回的数据格式都是固定的,我们在请求成功里边的处理,也是有很多重复的代码,这种情况,就需要封装了,可以这样写:

- (void)universalNetworkRequestWithNetConnectType:(RequestType)type requestURL:(NSString *)url model:(Class)modelClass para:(NSDictionary *)para success:(SuccessBlock)success successCodeError:(SuccessBlock)successCodeError fail:(DefeatedBlock)fail netError:(NetworkError)netError;

解释一下参数,RequestType:定义的请求方式枚举(get post等)。model:如果数据请求成功,需要将数据转化成这个model。para:请求参数。success:数据请求成功(根据后台的返回码来确定)。successCodeError:网络请求成功,但是返回的数据不是你要的数据(比如数据正确是200,但是有时候根据业务需求,会返回别的码,比如你在别的地方登录了什么的)。fail:网络请求失败。netError:没有网络。
方法实现部分:

if ([RNetStatus networkIsAvailable]) {
        NSMutableDictionary *dic = [NSMutableDictionary dictionaryWithDictionary:para];
        switch (type) {
            case get:
                [self getNetworkRequestWithNetConnectRequestURL:url model:modelClass para:dic success:success successCodeError:successCodeError fail:fail];
                break;
            case post:
                [self postNetworkRequestWithNetConnectRequestURL:url model:modelClass para:dic success:success successCodeError:successCodeError fail:fail];
                break;
            case upload:
                //上传暂时没写,后期会补上
                break;
        }
    }else{
        netError();
    }

根据不同的方法,来调afn响应的方法,这里,我只写出一个get请求的实现,post是一样的

- (void)getNetworkRequestWithNetConnectRequestURL:(NSString *)url model:(Class)model_class para:(NSDictionary *)para success:(SuccessBlock)success successCodeError:(SuccessBlock)successCodeError fail:(DefeatedBlock)fail{

    [self.sessinoManager GET:url parameters:para progress:^(NSProgress * _Nonnull downloadProgress) {
        
    } success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        REFLog(@"--request success --%@--para is --%@", responseObject, para);
        
        if ([responseObject[@"resCode"] intValue] == 200) {
            if (model_class == nil) {
                success(responseObject[@"data"]);
            }else{
                //如果data是数组,并且只有一层数据结构
                if ([responseObject[@"data"] isKindOfClass:[NSArray class]]) {
                    NSArray *result = [model_class mj_objectArrayWithKeyValuesArray:responseObject[@"data"]];
                    success(result);
                }else{//data直接就是一个字典
                    success([model_class mj_objectWithKeyValues:responseObject[@"data"]]);
                }
            }
        }else{
                successCodeError(responseObject[@"resMsg"]);
            }
        }

    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        fail(error);
    }];
}

解释一下代码:
如果model不是nil,意思就是得到的数据,可以转化成model,这里,就只是处理了返回的数据直接能转化成model,或者返回的数据是个数组,数组里存的就是字典。如果数据层级很多,这个方法是不适用的,或者写出一个单独的处理数据的函数来处理也是可以的,毕竟层级很多的数据,不是太多。
这里的sessionManager,是一个AFHTTPSessionManager的属性,可以这样懒加载一下

- (AFHTTPSessionManager *)sessinoManager {
    if (!_sessinoManager) {
        _sessinoManager = [[AFHTTPSessionManager manager] initWithBaseURL:base_URL];
        _sessinoManager.requestSerializer.timeoutInterval = kTimeOut;
    }
    return _sessinoManager;
}

直接设置baseurl和超时时间。
使用的时候,可以这样

[[REFNetworkManager manager] universalNetworkRequestWithNetConnectType:get requestURL:@"" model:[Model class] para:@{@"":@""}success:^(id response) {
        [SVProgressHUD dismiss];
    } successCodeError:^(id response) {
        [SVProgressHUD showSuccessWithString:response];
        [refreshComponent endRefreshing];
    } fail:^(NSError *error) {
        [SVProgressHUD showNetTimeout];
    } netError:^{
        [SVProgressHUD showNetWorkError];
    }];

这里,可以自己对SVProgressHUD进行一个简单的封装,用起来也是很方便的。
至于这里边的单利,block之类的,就不一一写出来了,不会的可以自行百度,很简单。

你可能感兴趣的:(AFN的二次封装使用)