2016-09-22 30 views
0

我想向服務器發出多個請求,以一個接一個地獲取帖子和評論。所以,我用dispatch_group創建了這個例子,它將一個接一個地串行讀取所有的POSTS,然後在POSTS完成之後,它會一個接一個地讀取註釋。使用dispatch_group嵌套多個請求

下面是關於這是如何工作的粗略模式。

  • 取後1
  • 取柱2
  • 取柱3
  • ....
  • 取柱50
  • 抓取評論1
  • 抓取評論2
  • 。 ..
  • Fetch comment 50

所以,所有這些都應該如圖所示連續工作,就像它拿到帖子1,完成並取出帖子2完成等等。

以下示例適用於此目的。但是,現在我想要回電話以真正知道何時完成了50個帖子的同步,以及何時完成了50個評論。我嘗試在requestOne和requestTwo中的for循環之後添加dispatch_group_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

我想你想要做的是以下幾點。請注意,這樣做是爲了在完成所有50個調用後調用requestTwoCompletionrequestOneCompletion的每個完成塊。無法保證50次通話的順序。

我所做的主要更改是dispatch_group_t是每種方法的本地方法,我在for循環之外移動了dispatch_group_wait。在這種情況下,它會消除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旁邊。