(注意:你甚至可以在不阅读我的任何代码的情况下回答这个问题,如果你不想阅读这个问题小说,我已经在底部解释过)
我有一些代码让我有些偏离了方向。似乎我的代码[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
,我希望它显示,直到所有数据都已正确加载。我不知道如何找出完成处理程序何时完成,以及它到底是什么..