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 最初是空的,但大约半秒后,它会在正确的游戏数量中填充“Game vs.Nobody”。如果我开始两个游戏,然后重新进入视图控制器,那么它一开始是空白的,然后在两个单元格上显示“Game vs.Nobody”。但是:如果我滚动屏幕外的行,并强制他们cellForRowAtIndexPath再次调用,则会显示正确的名称。所以似乎[tableView reloadData]viewDidAppear我要求它之前调用了 in ,在填充了名称的数组之前。

我认为这与整个 CompletionHandler 相关,因为我以前从未使用过它,但我认为 CompletionHandler 中的所有内容都应该按时间顺序发生?有什么我可以打电话的,比如onCompletion{}什么?

理想情况下,我希望 UIAlertView 或带有旋转轮显示的东西UIActivityIndicationView,我希望它显示,直到所有数据都已正确加载。我不知道如何找出完成处理程序何时完成,以及它到底是什么..

4

1 回答 1

1

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

要修复,只需在 loadPlayersForIdentifiers 的完成块内移动 reload 调用(最后)

于 2013-05-03T20:54:57.763 回答