看起来像我的应用程序正在做的东西错误的顺序
(注意:如果你不想读这个问题的小说,我可以解释底部)看起来像我的应用程序正在做的东西错误的顺序
我有一些代码让我有点偏离课程。在数据准备就绪之前,我的代码似乎正在调用[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就完成了,它到底是什么..
的playerNames阵列被填充完成处理程序中为loadPlayersForIdentifiers
,这是(我认为)是异步的。在完成处理程序运行之前,不会填充名称数组,但在另一个块内调用[tableView reloadData]
。
要解决,只是移动重装通话结束块内的loadPlayersForIdentifiers(末)
那你要我把它('loadPlayersForIdentifiers')方法中的for循环,这样就会意味着整个表格会在列表中每次重新加载一次..但是我想我可以将该方法移到for循环外面,并向所有收集的对手发送数组..我会试一试。 – Sti 2013-05-03 20:58:36
这就像一个魅力!谢谢。我将'loadPlayersForIdentifiers'移到了for-loop之外,并且让循环将所有PlayerID收集到currentParticipants中,我将其转换为数组,然后将整个playerID的数组(现在用于所有游戏而不是每场比赛)发送到' loadPlayersForIdentifiers',并将'[tableView reloadData]'移到此调用的结尾。我想我应该阅读一些异步的东西。 – Sti 2013-05-03 21:29:04