我想向服务器发出多个请求,一个接一个地获取帖子和评论。所以,我用dispatch_group创建了这个例子,它一个接一个地串行获取所有的POSTS,然后在完成POSTS之后,它一个接一个地获取注释。
以下是关于其工作原理的粗略架构。
所以,所有这些应该如图所示连续工作,就像它取出第1个帖子一样,然后完成,然后获取第2个结束,依此类推。
以下示例适用于此目的。但是,现在我想回电话,实际知道50个帖子的同步完成和50个评论完成时。我尝试通过在requestOne和requestTwo中的for循环之后添加dispatch_group_notify。但是,当所有任务都已完成时,似乎会调用notify方法。怎么能实现呢?我不是母语为英语的人,请写下如果我需要改进帖子,我仍然可以尝试:)
@interface GroupTest ()
@property (nonatomic, readonly) dispatch_group_t group;
@property (nonatomic, readonly) dispatch_queue_t serialQueue;
@end
@implementation GroupTest
- (instancetype)init
{
if (self = [super init]) {
_group = dispatch_group_create();
_serialQueue = dispatch_queue_create("com.test.serial.queue",
DISPATCH_QUEUE_SERIAL);
}
return self;
}
- (void)start
{
dispatch_async(self.serialQueue, ^{
[self requestOneCompletion:^{
NSLog(@"Request 1 completed");
}];
[self requestTwoCompletion:^{
NSLog(@"Request 2 completed");
}];
});
}
- (void)requestTwoCompletion:(void(^)(void))completion
{
for (NSUInteger i = 1; i <= 50; i++) {
dispatch_group_enter(self.group);
[self requestComment:i
completion:^(id response){
NSLog(@"%@", response);
dispatch_group_leave(self.group);
}];
dispatch_group_wait(self.group, DISPATCH_TIME_FOREVER);
}
}
- (void)requestOneCompletion:(void(^)(void))completion
{
for (NSUInteger i = 1; i <= 50; i++) {
dispatch_group_enter(self.group);
[self requestPost:i
completion:^(id response){
NSLog(@"%@", response);
dispatch_group_leave(self.group);
}];
dispatch_group_wait(self.group, DISPATCH_TIME_FOREVER);
}
}
- (void)requestComment:(NSUInteger)comment
completion:(void(^)(id))completion
{
NSString *urlString = [NSString stringWithFormat:@"https://jsonplaceholder.typicode.com/comments/%lu", (unsigned long)comment];
NSURLSession *session = [NSURLSession sharedSession];
NSURLSessionDataTask *dataTask = [session dataTaskWithURL:[NSURL URLWithString:urlString]
completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
id object = [NSJSONSerialization JSONObjectWithData:data
options:0
error:nil];
completion(object);
}];
[dataTask resume];
}
- (void)requestPost:(NSUInteger)post
completion:(void(^)(id))completion
{
NSString *urlString = [NSString stringWithFormat:@"https://jsonplaceholder.typicode.com/posts/%lu", (unsigned long)post];
NSURLSession *session = [NSURLSession sharedSession];
NSURLSessionDataTask *dataTask = [session dataTaskWithURL:[NSURL URLWithString:urlString]
completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
id object = [NSJSONSerialization JSONObjectWithData:data
options:0
error:nil];
completion(object);
}];
[dataTask resume];
}
@end
答案 0 :(得分:1)
我认为您想要做的是以下内容。请注意,这样做是为了在完成所有50次调用后调用requestTwoCompletion
和requestOneCompletion
的每个完成块。 50个电话的顺序无法保证。
我所做的主要更改是dispatch_group_t
是每个方法的本地更改,我将dispatch_group_wait
移到for
循环之外。在这种情况下,它会消除completion
的好处,因为等待将阻止单位完成。如果您坚持使用完成并且没有阻止,则可以将其全部包含在dispatch_async
中。
- (void)requestTwoCompletion:(void(^)(void))completion
{
dispatch_group_t group = dispatch_group_create();
for (NSUInteger i = 1; i <= 50; i++) {
dispatch_group_enter(group);
[self requestComment:i
completion:^(id response){
NSLog(@"%@", response);
dispatch_group_leave(group);
}];
}
dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
completion();
}
- (void)requestOneCompletion:(void(^)(void))completion
{
dispatch_group_t group = dispatch_group_create();
for (NSUInteger i = 1; i <= 50; i++) {
dispatch_group_enter(group);
[self requestPost:i
completion:^(id response){
NSLog(@"%@", response);
dispatch_group_leave(group);
}];
}
dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
}
由于这是在一个串行队列中,这将是requestOneCompletion
将完成所有50,然后requestTwoCompletion
将运行所有50下一个。