0

我正在使用 Game Center 和GKTurnBasedMatch.

为了在我的根控制器的表格视图中显示游戏列表,我调用了以下方法:

-(void)reloadTableView
{    
    self.matchesTable.hidden = YES;
    [_activityIndicator startAnimating];

    [GKTurnBasedMatch loadMatchesWithCompletionHandler: ^(NSArray *matches, NSError *error)
     {
         if (error)
         {
             NSLog(@"loadMatchesWithCompletionHandler error:- %@", error.localizedDescription);

         } else
         {
             for (GKTurnBasedMatch *m in matches)
             {
                 // Download match data for each match
                 [m loadMatchDataWithCompletionHandler:^(NSData *matchData, NSError *error)
                  {
                      if (error)
                      {
                          NSLog(@"loadMatchDataWithCompletionHandler:- %@", error);

                      } else
                      {
                          [self processMatches]; // extracts match data to use in UI
                      }

                  }];

                 // Snipped - Code here to add each match to the relevant array ('My turn', 'Their turn' or 'Game over') for display in the table
             }

             [self.matchesTable reloadData];

             self.matchesTable.hidden = NO;
             [_activityIndicator stopAnimating];
        }
    }]; 
}

我希望任务的顺序是:

1) 隐藏matchesTable并启动活动指示器
2) 调用loadMatchesWithCompletionHandler
3) 对于每场比赛,调用loadMatchDataWithCompletionHandler
4)[self processMatches]在每场比赛上调用
5) 将每场比赛放入相关数组
6) 停止活动指示器并显示matchesTable

但是,代码一直运行得如此之快,以至于在任何匹配数据有时间下载之前执行第 6 点,这意味着旧数据显示在我的表中。

所以我的大问题是:如何让程序等到每场比赛都下载了比赛数据,然后再继续执行其余的方法?(即在第 4 点后暂停,只有在每场比赛的比赛数据下载完成后才开始第 5 点)

4

1 回答 1

0

因为您在loadMatchDataWithCompletionHandler现有的完成块 for 中使用额外的完成块循环调用loadMatchesWithCompletionHandler,所以它会触发加载匹配数据的调用而不等待它们的响应,然后它会调用您的表重新加载方法,然后是您的完成处理程序以进行加载匹配数据开始触发(或者在重新加载表的同时,没有真正的方法来指定您的代码)。

我建议改为使用 GCD 来触发您的请求。这样,您可以将它们排入dispatch_async. 如果可能的话,它将需要重新配置调用以获取您的匹配/数据。像这样的东西:

self.matchesTable.hidden = YES;
[_activityIndicator startAnimating];

dispatch_queue_t myQueue = dispatch_queue_create("My Queue",NULL);
dispatch_async(myQueue, ^{
    NSError *error;
    NSArray *matches = [GKTurnBasedMatch loadMatches:&error];

    if(error)
        NSLog(@"Failed");
    else
    {
        for(GKTurnBasedMatch *m in matches)
        {
            // This will be on BG thread, but will ensure all calls are made before reloading table
            NSData *matchData = [m loadMatchData:&error];

            if(error)
                NSLog(@"Failed");
            else
                [self processMatches];

            // Snipped - Code here to add each match to the relevant array ('My turn', 'Their turn' or 'Game over') for display in the table
        }
    }

    dispatch_async(dispatch_get_main_queue(), ^{
        [self.matchesTable reloadData];

        self.matchesTable.hidden = NO;
        [_activityIndicator stopAnimating];

    });
});

编辑:
根据您的评论,这种结构是不可能的。我想你可以做的其他事情是知道需要拨打的电话数量,并在每次通话结束时增加一些东西。如果您已达到最大值,请进行更新。

...
int count = 0;
for (GKTurnBasedMatch *m in matches)
{
    // Download match data for each match
    [m loadMatchDataWithCompletionHandler:^(NSData *matchData, NSError *error)
     {
         count++;
         if (error)
         {
             NSLog(@"loadMatchDataWithCompletionHandler:- %@", error);
         } else
         {
             [self processMatches]; // extracts match data to use in UI
         }

         if(count == matches.count)
         {
             [self.matchesTable reloadData];

             self.matchesTable.hidden = NO;
             [_activityIndicator stopAnimating];
         }
     }];

    // Snipped - Code here to add each match to the relevant array ('My turn', 'Their turn' or 'Game over') for display in the table
}
于 2014-05-27T14:12:35.200 回答