2013-05-03 24 views
0

(注意:如果你不想读这个问题的小说,我可以解释底部)看起来像我的应用程序正在做的东西错误的顺序

我有一些代码让我有点偏离课程。在数据准备就绪之前,我的代码似乎正在调用[tableView reloadData],但我在调用reloadData之前设置了数据。这可能是一个新手问题,但我从来没有处理过这种代码,如果有人能够向我解释发生了什么,以及为什么我的某些代码被允许跳出来,我会非常高兴按照时间顺序逻辑..

我的问题与GameCenter无关,我认为这是一个普通的Objective-C的东西,但我正在用GameCenter体验它,所以即使你对GameCenter一无所知,你可能会明白我在说什么。

我有一个tableViewController,我用GameCenter中的匹配(游戏)填充tableView,并显示对手的名字(在我的回合制游戏中总是一个对手)。

我在viewDidAppear把这个:

[GKTurnBasedMatch loadMatchesWithCompletionHandler:^(NSArray *matches, NSError *error) {  
//Gets an array (*matches) of GKTurnBasedMatches(All matches the local player is involved in) 
    if(error) 
    { 
     NSLog(@"Load matches error: %@", error.description); 
     return; 
    } 
    //putting them in an array 
    matchList = [[NSArray alloc] initWithArray:matches];  

    //So far only for testing purposes: I am creating an array for player names: 
    playerNames = [[NSMutableArray alloc] init]; 
    for(GKTurnBasedMatch* mat in matchList) 
    {//For every match in the array of matches, find the opponent: 
     GKTurnBasedParticipant *otherParticipant; //These games only have 2 players. Always. 
     for(GKTurnBasedParticipant *part in [mat participants]) 
     { //Loop through both participants in each match 
      if(NO == [part.playerID isEqualToString:[GKLocalPlayer localPlayer].playerID]) 
      {//If the participant *part is NOT the local player, then he must be the opponent: 
       otherParticipant = part; //Save the opponent. 
      } 
     } 

     if(otherParticipant != nil && otherParticipant.playerID != nil) 
     { //If the opponent exists(like he does) 
      [GKPlayer loadPlayersForIdentifiers:@[otherParticipant.playerID] withCompletionHandler:^(NSArray *players, NSError *error) { 
       //Returns an array with only the opponent in it 
       if([(GKPlayer*)[players objectAtIndex:0] displayName]!=nil) 
       {//If he has a name: 
        NSString *nam = [[NSString alloc] initWithString:[(GKPlayer*)[players objectAtIndex:0] displayName]]; 
        //Add the name to the name-array 
        [playerNames addObject:nam]; 
       } 
       else 
       {//If he doesn't have a name, put "No name" into the name array(is not happening) 
        NSString *nam = [[NSString alloc]initWithString:@"No name"]; 
        [playerNames addObject:nam]; 
       }  
      }]; 
     } 
     else 
     {//If for some reason the entire opponent is nil or he doesn't have a playerID, which isn't happening, add "No name";(This is not happening) 
      [playerNames addObject:[NSString stringWithFormat:@"No name"]]; 
     } 
    } 
    //And THEN reload the data, now with the NSMutableArray 'playerNames' ready and filled with opponent's names. 
    [[self tableView] reloadData]; 
}]; 

这是我CellForRowAtIndexPath

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 
{ 
    static NSString *CellIdentifier = @"matchCell"; 
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath]; 

    NSString *name = @"Nobody"; 
    if(playerNames!=nil && [playerNames count]>indexPath.row) 
     name = [playerNames objectAtIndex:indexPath.row]; 
    [[cell textLabel] setText:[NSString stringWithFormat:@"Game vs. %@", name]]; 

    return cell; 
} 

事情是:显示视图控制器时:如预期的tableView最初空了,但大约半秒钟后,就会在正确数量的游戏中填充“游戏vs.无人”。如果我开始两场比赛,并重新进入视图控制器,那么它首先是空白的,然后在两个单元格上显示“Game vs. Nobody”。 但是:如果我滚动屏幕外的行,并强制他们再次调用cellForRowAtIndexPath,则显示正确的名称。所以在我提出之前调用viewDidAppear中的[tableView reloadData]似乎就是在名称数组填充之前调用的。

我认为这与整个CompletionHandler事情有关,因为我从来没有使用过这个,但我认为里面的所有 CompletionHandler应该按时间顺序发生?有什么我可以打电话,如onCompletion{}什么的?

理想情况下,我想要一个UIAlertView或其他东西来显示一个旋转轮,UIActivityIndicationView,我希望它显示,直到所有数据已正确加载。我不知道如何找出WHEN的completionHandler就完成了,它到底是什么..

回答

1

的playerNames阵列被填充完成处理程序中为loadPlayersForIdentifiers,这是(我认为)是异步的。在完成处理程序运行之前,不会填充名称数组,但在另一个块内调用[tableView reloadData]

要解决,只是移动重装通话结束块内的loadPlayersForIdentifiers(末)

+0

那你要我把它('loadPlayersForIdentifiers')方法中的for循环,这样就会意味着整个表格会在列表中每次重新加载一次..但是我想我可以将该方法移到for循环外面,并向所有收集的对手发送数组..我会试一试。 – Sti 2013-05-03 20:58:36

+0

这就像一个魅力!谢谢。我将'loadPlayersForIdentifiers'移到了for-loop之外,并且让循环将所有PlayerID收集到currentParticipants中,我将其转换为数组,然后将整个playerID的数组(现在用于所有游戏而不是每场比赛)发送到' loadPlayersForIdentifiers',并将'[tableView reloadData]'移到此调用的结尾。我想我应该阅读一些异步的东西。 – Sti 2013-05-03 21:29:04

相关问题