dispatch_group 并发请求工具类封装

2020-10-12  本文已影响0人  辛乐

参考文章:https://www.jianshu.com/p/54bbacfcc31b

上边文章中描述的问题和解决思路都是十分清晰的,十分感谢,下边代码是我自己的项目中的应用,外带针对自己实际情况做的优化.

因为会用到method_exchangeImplementations交换方法,为了不影响目前项目中的HttpRequestTool正常请求的工具类,这里单独创建了HttpGroupRequestTool 工具类,将代码影响降到新加的工具类,而HttpGroupRequestTool新工具类中的基本网络调用只是包了一层的HttpRequestTool,这样代码保证安全的同时也增加可扩展性,增加了GET POST等不同类型请求的判断替换.至于HttpRequestTool中的代码,就不放了,大同小异.

typedef void(^BlockAction)(void);
typedef void(^BlockResponse)(id responseObject);
typedef void(^BlockResponseFailure)(NSError * error);
typedef void(^GroupResponseFailure)(NSArray * errorArray);

@interface HttpGroupRequestTool : NSObject

-(void)sendRequestWithMethod:(NSString *)method url:(NSString *)url param:(NSDictionary *)param thenSuccess:(BlockResponse)success fail:(BlockResponseFailure)fail;

/**
 *  并发组请求
 *
 *  @param requests 并发的请求,block中正常执行请求操作
 *  @param success  全部请求success后执行
 *  @param failure  只要有一个请求failure后执行
 */
- (void)sendGroupRequest:(BlockAction)requests success:(BlockAction)success failure:(GroupResponseFailure)failure;

+ (instancetype)sharedInstance;

.m

#import <objc/runtime.h>
#import "HttpGroupRequestTool.h"
#import "HttpRequestTool.h"

static char groupErrorKey;
static char queueGroupKey;

@implementation HttpGroupRequestTool

+ (instancetype)sharedInstance {
    
    static id obj = nil;
    
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        obj = [[self alloc] init];
    });
    return obj;
}


-(void)sendRequestWithMethod:(NSString *)method url:(NSString *)url param:(NSDictionary *)param thenSuccess:(BlockResponse)success fail:(BlockResponseFailure)fail{
    if ([method.lowercaseString isEqualToString:@"get"]) {
        [self sendGetRequestWith:url param:param thenSuccess:success fail:fail];
    }else{
        [self sendPostRequestWith:url param:param thenSuccess:success fail:fail];
    }
}

- (void)sendGroupRequest:(BlockAction)requests success:(BlockAction)success failure:(GroupResponseFailure)failure {
    if (requests == nil) {
        return;
    }
    
    dispatch_group_t group = dispatch_group_create();
    objc_setAssociatedObject(group, &groupErrorKey, [NSMutableArray array], OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    
    Method originalPost = class_getInstanceMethod(self.class, @selector(sendRequestWithMethod:url:param:thenSuccess:fail:));
    Method groupPost = class_getInstanceMethod(self.class, @selector(sendRequestInGroupMethod:Url:withData:success:failure:));
    
    NSOperationQueue *queue = [[NSOperationQueue alloc] init];
    objc_setAssociatedObject(queue, &queueGroupKey, group, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    queue.qualityOfService = NSQualityOfServiceUserInitiated;
    queue.maxConcurrentOperationCount = 3;
    
    [queue addOperationWithBlock:^{
        
        method_exchangeImplementations(originalPost, groupPost);
        requests();
        // 发出请求后就可以替换回original method,不必等待回调,尽量减小替换的时间窗口
        method_exchangeImplementations(originalPost, groupPost);
        
        dispatch_group_notify(group, dispatch_get_main_queue(), ^{
            NSMutableArray *arrayM = objc_getAssociatedObject(group, &groupErrorKey);
            if (arrayM.count > 0) {
                if (failure) {
                    failure(arrayM.copy);
                }
            } else if (success) {
                success();
            }
            
        });
    }];
}

//TODO: -- 私有方法
-(void)sendGetRequestWith:(NSString *)url param:(NSDictionary *)param thenSuccess:(BlockResponse)success fail:(BlockResponseFailure)fail{
    [HttpRequestTool xlGroupRequestApiWithMethodGet:url param:param.mutableCopy thenSuccess:success fail:fail];
}

-(void)sendPostRequestWith:(NSString *)url param:(NSDictionary *)param thenSuccess:(BlockResponse)success fail:(BlockResponseFailure)fail{
    [HttpRequestTool xlGroupRequestApiWithMethodPost:url param:param.mutableCopy thenSuccess:success fail:fail];
}

- (void)sendRequestInGroupMethod:(NSString *)method Url:(NSString *)strURL withData:(NSDictionary *)data success:(BlockResponse)success failure:(BlockResponseFailure)failure {
    
    dispatch_group_t group = objc_getAssociatedObject([NSOperationQueue currentQueue], &queueGroupKey);
    
    // 如果是非组请求
    if (group == nil) {
        // 执行original method
        [self sendRequestInGroupMethod:method Url:strURL withData:data success:success failure:failure];
        return;
    }
    
    dispatch_group_enter(group);
    // 执行original method
    [self sendRequestInGroupMethod:method Url:strURL withData:data success:^(id responseObject) {
        
        if (success) {
            success(responseObject);
        }
        
        dispatch_group_leave(group);
    } failure:^(NSError *error) {
        NSMutableArray *arrayM = objc_getAssociatedObject(group, &groupErrorKey);
        [arrayM addObject:error];
        
        if (failure) {
            failure(error);
        }
        
        dispatch_group_leave(group);
    }];
}

@end

demo使用示例

HttpGroupRequestTool *tool = [HttpGroupRequestTool sharedInstance];
 __block id responseObject1,responseObject2,responseObject3;
 [tool sendGroupRequest:^{
     
     [tool sendRequestWithMethod:@"GET" url:XLTicker param:@{@"symbol":@"ALL"} thenSuccess:^(id  _Nonnull responseObject) {
         responseObject1 = responseObject;
     } fail:^(NSError * _Nonnull error) {
         LOG(@"~~~%@~~~",error);
     }];
 
     [tool sendRequestWithMethod:@"GET" url:XLOrderBook param:@{@"symbol":@"BTC-USDT"} thenSuccess:^(id  _Nonnull responseObject) {
         responseObject2 = responseObject;
     } fail:^(NSError * _Nonnull error) {
         LOG(@"~~~%@~~~",error);
     }];
     
     NSMutableDictionary *params = @{
                                     @"type":@"add",
                                     @"marketType":@"USDT",
                                     @"coinType":@"BTC",
                                     }.mutableCopy;
     [tool sendRequestWithMethod:@"POST" url:XLCollectHandle param:params thenSuccess:^(id  _Nonnull responseObject) {
         responseObject3 = responseObject;
     } fail:^(NSError * _Nonnull error) {
         
     }];
 
 } success:^{
     //成功
     LOG(@"~~~组合数据成功:%@ - %@ - %@~~~",responseObject1,responseObject2,responseObject3);
 } failure:^(NSArray * _Nonnull errorArray) {
     //失败
     LOG(@"~~~组合数据失败:%@",errorArray);
 }];
上一篇下一篇

猜你喜欢

热点阅读