dispatch_group 并发请求工具类封装

参考文章:http://08643.cn/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);
 }];
最后编辑于
?著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,100评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,308评论 3 388
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事?!?“怎么了?”我有些...
    开封第一讲书人阅读 159,718评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,275评论 1 287
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,376评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,454评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,464评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,248评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,686评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,974评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,150评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,817评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,484评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,140评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,374评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,012评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,041评论 2 351