使用dispatch_group

时间:2016-09-22 15:10:03

标签: ios objective-c grand-central-dispatch

我想向服务器发出多个请求,一个接一个地获取帖子和评论。所以,我用dispatch_group创建了这个例子,它一个接一个地串行获取所有的POSTS,然后在完成POSTS之后,它一个接一个地获取注释。

以下是关于其工作原理的粗略架构。

  • 获取帖子1
  • 获取帖子2
  • 获取帖子3
  • ....
  • 获取帖子50
  • 获取评论1
  • 获取评论2
  • ...
  • 获取评论50

所以,所有这些应该如图所示连续工作,就像它取出第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

1 个答案:

答案 0 :(得分:1)

我认为您想要做的是以下内容。请注意,这样做是为了在完成所有50次调用后调用requestTwoCompletionrequestOneCompletion的每个完成块。 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下一个。