(注意:如果你不想讀這個問題的小說,我可以解釋底部)看起來像我的應用程序正在做的東西錯誤的順序
我有一些代碼讓我有點偏離課程。在數據準備就緒之前,我的代碼似乎正在調用[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就完成了,它到底是什麼..
那你要我把它('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