AFN循环请求来由
对于搞iOS的来说,AFN这个库无疑是必需品,然而偶尔会遇到这样的想法:我需要循环发送网络请求,并且还需要再每个网络请求返回后进行一系列操作,操作完后再进行下一个处理,关键的在每一个操作结束的时候会增删改数据,这样跟顺序处理就很相关了。但是AFN是每个请求都是在一个新的异步线程上面执行,这就很难控制到了。
处理方式:GCD信号量
// 创建队列组,可以使多个网络请求异步执行,执行完之后再进行操作
dispatch_group_t group = dispatch_group_create();
//自定义队列
dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
dispatch_group_async(group, queue, ^{
// 循环上传数据
for (int i = 0; i < self.array.count; i++) {
//创建dispatch_semaphore_t对象
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
for (NSString *name in cacheFileNameArray) {
if ([name hasSuffix:@".plist"]){ //如果有plist后缀的文件,说明就是存储的购买凭证
//创建dispatch_semaphore_t对象
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
NSString *plistPath = [NSString stringWithFormat:@"%@/%@", [ZHJSandBoxPathTool iapOrderPath], name];
NSDictionary *dic = [NSDictionary dictionaryWithContentsOfFile:plistPath];
if ([dic notEmpty]) {
NSString *kdusr = dic[kdusrKey];
NSString *token = dic[kdTokenKey];
NSString *orderID = dic[orderIDKey];
NSString *receipt = dic[receiptKey];
[ZHJNetIdTool verificateInAppPurchaseOrderWithKdusr:kdusr KdToken:token order_id:orderID pay_type:@19 receipt:receipt success:^(ZHJNetCommonResult *obj) {
if (obj.returnCode.integerValue == 0) {
//重新验证成功
[self removeReceiptWithPath:plistPath];
dispatch_semaphore_signal(semaphore);
} else {
dispatch_semaphore_signal(semaphore);
}
} failure:^(NSError *error) {
dispatch_semaphore_signal(semaphore);
}];
}
//信号量减1,如果>0,则向下执行,否则等待
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
}
}
}
});
// 当所有队列执行完成之后
dispatch_group_notify(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// 执行下面的判断代码
dispatch_async(dispatch_get_main_queue(), ^{
});
});
以上就是利用信号量值的增减控制的一种方式。
dispatch_ group_t
如果只是想要处理顺序发送网络请求,最后所有网络请求返回之后,再一并处理后续的操作的话,dispathch_ groupt 跟dispatch group_notify组合可以做到这一点。
NSString *str = @"https://baidu.com";
NSURL *url = [NSURL URLWithString:str];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
NSURLSession *session = [NSURLSession sharedSession];
dispatch_group_t testGroup = dispatch_group_create();
for (int i=0; i<16; i++) {
dispatch_group_enter(testGroup);
NSURLSessionDataTask *task = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
DebugLog(@"测试测试",i,i);
dispatch_group_leave(testGroup);
}];
[task resume];
}
dispatch_group_notify(downloadGroup, dispatch_get_main_queue(), ^{
NSLog(@"end");
DebugLog(@"循环结束 开始接下来的操作");
});
话外
其实YTNetwork这个框架对AFN的封装可以满足到这种循环的需求,他的调用方式是一种函数链式调用。而目前比较主流的RAC也是可以满足的。