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);
}];