2013-05-03 23 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

相關問題