美文网首页
AFN的二次封装使用

AFN的二次封装使用

作者: revon | 来源:发表于2017-11-21 16:22 被阅读218次

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

    - (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的二次封装使用

          本文链接:https://www.haomeiwen.com/subject/sdjwvxtx.html