使用AFNetworking3.0实现接口异步并发

近两个月,因为团队后台的动荡,项目新版本的接口非常乱,出现一个tableView需要几个接口来获取数据源的情况。这就需要在几个接口并发请求完后一起回调处理。

因为项目中使用的是AFN的网络框架,所以,这个需求只能基于AFN去实现


一般,我们在使用AFN的网络请求时,是利用

- (NSURLSessionDataTask *)POST:(NSString *)URLString
                    parameters:(id)parameters
                       success:(void (^)(NSURLSessionDataTask *task, id responseObject))success
                       failure:(void (^)(NSURLSessionDataTask *task, NSError *error))failure

去做接口请求。如果,直接用这个方法,代码如下

+(void)testRequest1{
    NSDictionary * params;
    [[AFNAsynNetwork sharedClient] POST:URL1 parameters:params success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        data1 = responseObject;
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        
    }];
    [[AFNAsynNetwork sharedClient] POST:URL2 parameters:params success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        data2 = responseObject;
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        
    }];
    [[AFNAsynNetwork sharedClient] POST:URL3 parameters:params success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        data3 = responseObject;
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        
    }];
}

+(void)testResult1{
    if (data1 && data2 && data3) {
        //数据整合操作
        
    }
}
由于是反面教材,所以这里写的比较粗暴,想要优雅点可以使用CGD或者NSOperation的并发。这样写的话,数据处理的操作都是在block回调主线后做的,有人会说,可以再让这些数据去子线做操作,当然,这些我也有考虑。总之,这样去实现,代码质量很差,而且对于大量接口和大量数据的处理的扩展性不高。于是,我只能另辟蹊径。

在AFN3.0中,网络请求已经都改成了NSURLSession。如果对NSURLSession有所了解的话,会知道NSURLSession的网络请求回调是在NSURLSessionDataDelegate中回调的

- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask
                                     didReceiveData:(NSData *)data;
而且,不一定是一次返回所有数据,需要用 NSMutableData去多次接收。在AFN中,其实已经将这个代理方法封装成了block,而且这个方法中获取的数据是在子线中的,可以将请求到的数据直接拿出来在子线程中做数据操作,只要完成数据操作,在最后回调给主线程即可。

- (void)setDataTaskDidReceiveDataBlock:(void (^)(NSURLSession *session, NSURLSessionDataTask *dataTask, NSData *data))block

具体实现请看代码

+(void)getDataBlock:(block)block{
    NSMutableArray * dataArray = [NSMutableArray array];
    NSMutableArray * errors = [NSMutableArray array];
    
    //两个不需要回调的网络请求
    NSURLSessionDataTask * task1 = [AFNAsynPost asynPostProductWithBlock:nil];
    NSURLSessionDataTask * task2 = [AFNAsynPost asynPostBanner];
    
    NSArray * requestArr = @[task1,task2];
    __block NSInteger requestCount = 0;
    [self getSuccessAndFailure:^(NSURLSession *session, NSURLSessionDataTask *dataTask, NSData *data, NSError *error) {
        
        requestCount++;
        
        if (data) {
            id json = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:nil];
            
            if ([json[@"respCode"] isEqualToString:@"00"]) {
                if (dataTask.taskIdentifier == task1.taskIdentifier) {
                    [dataArray addObject:json];
                }else{
                    NSLog(@"%@", json);
                    [dataArray addObject:json];
                }
            }else{
                [errors addObject:json];
            }
            
            
            
            if (requestCount == requestArr.count) {
                block(dataArray, errors);
            }
        }
        
        if (error) {
            [errors addObject:error];
            if (requestCount == requestArr.count) {
                block(dataArray, errors);
            }
        }
    }];
}

//中间变量,用于区分不同接口返回的数据
NSUInteger tempTaskIdentifier;
//用于拼接一个接口多次返回的数据
NSMutableData * tempData;

+(void)getSuccessAndFailure:(void (^)(NSURLSession *session, NSURLSessionDataTask *dataTask, NSData *data,NSError *error))block{
    AFNAsynNetwork * manager = [AFNAsynNetwork sharedClient];
    [manager setDataTaskDidReceiveDataBlock:^(NSURLSession * _Nonnull session, NSURLSessionDataTask * _Nonnull dataTask, NSData * _Nonnull data) {
        
        if (tempTaskIdentifier != dataTask.taskIdentifier) {
            tempTaskIdentifier = dataTask.taskIdentifier;
            tempData = [NSMutableData data];
        }
        
        [tempData appendData:data];
        
        NSLog(@"接收到服务器的数据(可能调用多次):%s\n%@\n%lf", __func__, data, (double)dataTask.countOfBytesExpectedToReceive);
        
        NSLog(@"json解析:%@",data);
        if (data) {
            
            id json = [NSJSONSerialization JSONObjectWithData:tempData options:NSJSONReadingMutableContainers | NSJSONReadingMutableLeaves error:nil];
            NSLog(@"%@",json);
            
            block(session, dataTask,data,nil);
        }
        
    }];
    
    [manager setTaskDidCompleteBlock:^(NSURLSession * _Nonnull session, NSURLSessionTask * _Nonnull task, NSError * _Nullable error) {
        NSLog(@"error:%@",error.localizedDescription);
        if (error) {
            block(session,(NSURLSessionDataTask *)task,nil,error);
        }
    }];
}







你可能感兴趣的:(iOS)