2016-09-22 20 views
0

投稿とコメントを次々にフェッチするために、複数のリクエストをサーバーに送信したいと思います。ですから、私はこの例をdispatch_groupで作成しました。これはすべてのPOSTSを連続してフェッチし、POSTSで終了した後、次々とコメントをフェッチします。dispatch_groupでネストされた複数のリクエスト

これは、この仕組みについての概略的なスキーマです。

  • ポスト1
  • フェッチポストフェッチ2
  • ポスト50
  • コメントフェッチコメントフェッチフェッチポスト3
  • を....フェッチ。 ..
  • コメントを取得する50

これらは、ポスト1をフェッチし、ポスト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

私は何がやりたいことは以下のとおりであると考えを試すことができ書き留めてください。これは、requestTwoCompletionrequestOneCompletionの各完了ブロックが、50回の呼び出しがすべて完了した後に呼び出されるようになっていることに注意してください。 50件の通話の順序は保証されていません。

主な変更点は、dispatch_group_tは各メソッドにローカルであり、dispatch_group_waitforループの外に移動しました。この場合、待機はユニットがブロックされるので、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を実行しますです。

関連する問題