【问题标题】:GameCenter Player Id to AliasGameCenter 玩家 ID 到别名
【发布时间】:2013-11-21 14:29:16
【问题描述】:

在我的应用程序中,我尝试将 GameCenter 玩家 ID 转换为他们的别名。收到 ID 后,我会从循环中调用以下方法。该方法一次使用一个 id 调用,并且应该返回一个别名。我只是想返回一个别名,但无法让它工作。起初我把退货放在块里,但我发现你不能在里面退货。现在我已经设置好了,所以它将对象添加到数组并在块之后返回,但是它给了我以下错误:[__NSArrayM objectAtIndex:]: index 0 beyond bounds for empty array'。任何帮助将不胜感激。

@property (nonatomic, strong, retain) NSMutableArray * playerScores;

.

-(void)getScoresAndAliasForLeaderboard{
 [GKLeaderboard loadLeaderboardsWithCompletionHandler:^(NSArray *leaderboards, NSError *nsError) {
        if( nsError != nil )
        {
            //error( nsError, "get leaderboard score" ) ;
            return ;
        }

        for( GKLeaderboard* board in leaderboards )
        {
            board.timeScope = GKLeaderboardTimeScopeAllTime;
            board.playerScope = GKLeaderboardPlayerScopeGlobal;
            board.range = NSMakeRange(1, 100);

            [board loadScoresWithCompletionHandler:^(NSArray *scores, NSError *error) {
                 NSLog(@"board: %@",board.description);

                NSLog(@"error: %@",error);
                if (error == nil)
                {
                    for (GKScore *s in scores)
                    {

                        GCLeaderboardScore *playerScore = [[GCLeaderboardScore alloc] init];
                        playerScore.playerID = s.playerID;
                        playerScore.score = (int)s.value;
                        playerScore.rank = s.rank;
                        NSArray * player = [[NSArray alloc]initWithObjects:s.playerID, nil];
                        [self loadPlayerData:player];
                        playerScore.alias = [_playerScores objectAtIndex:0];
                        NSLog(@"alias: %@, score: %d",playerScore.alias ,playerScore.score);
                        [_dataMutableArray addObject: playerScore];
                    }
                    [self.tableView reloadData];
                }
            }];


        }
                }] ;

}

.

-(NSString*) loadPlayerData: (NSArray *) identifiers
{
    if(!_playerScores){
    _playerScores = [[NSMutableArray alloc]init];
    }
    [GKPlayer loadPlayersForIdentifiers:identifiers withCompletionHandler:^(NSArray *players, NSError *error)
     {

         if (error != nil)
         {
             // Handle the error.
         }
         if (players != nil)
         {
                 GKPlayer* player = [players objectAtIndex:0];
                 [_playerScores addObject:player.alias];
         }
     }];

    return [_playerScores objectAtIndex:0];
}

【问题讨论】:

    标签: ios iphone ios7 game-center leaderboard


    【解决方案1】:

    loadPlayersForIdentifiers: withCompletionHandler: 异步加载播放器,因此是完成处理程序。当时您对于[_playerScores objectAtIndex:0] 尚未调用完成处理程序并且playerScores 为空。这就是您看到错误的原因。

    对于任何解决方案,您都必须接受异步就是异步。对于一个非常简单的解决方案,您可以让 loadPlayerData: 不返回任何内容 (void)。 _playerScores 已经看起来像一个成员变量,您可以在以后反复检查它。

    编辑:引用明确指出在主线程上调用完成处理程序:

    稍后,当任务完成时,Game Kit 会调用您的完成处理程序。完成处理程序总是在主线程上调用。

    这很好,因为这样您就可以从加载别名的完成处理程序中安全地调用[self.tableView reloadData];。但是,根据您的编辑,另外两个问题变得清晰:

    1. for 循环中loadScoresWithCompletionHandler: 的完成处理程序中的scores 内,您重复实例化数组player 用于传递给loadPlayerData: 的玩家ID。最好先填充这个数组,然后使用所有玩家 ID 一次调用 loadPlayerData:

    2. 即使您调用[self.tableView reloadData]loadPlayerData: 也不会完成它的工作,因为loadPlayersForIdentifiers: 是异步工作的。

    为了快速解决问题,我可能希望简化查询玩家别名的方式,并仅在玩家别名从 Game Center 服务器到达后更新您的表格视图。

    [board loadScoresWithCompletionHandler:^(NSArray *scores, NSError *error) {
        if (error)
        {
            return;
        }
        NSArray *player_ids = [[NSMutableArray alloc] init];
        for (GKScore *s in scores)
        {
            [player addObject:s.playerID];
        }
        [self loadPlayerData:player];
    }];
    

    我省略了您对实际分数的处理,以便更清楚地说明这一点。现在您只需加载玩家别名一次(拥有多个排行榜是您可能需要单独解决的另一个问题)。

    -(void)loadPlayerData:(NSArray *)identifiers
    {
        if (! _playerAliases) {
            _playerAliases = [[NSMutableDictionary alloc]init];
        }
        [GKPlayer loadPlayersForIdentifiers:identifiers
            withCompletionHandler:^(NSArray *players, NSError *error)
        {
            if ((error) || (! players))
            {
                return;
            }
            for (GKPlayer p in players)
            {
                [_playerAliases setObject:player.alias forKey::player.id];
            }
            [self.tableView reloadData];
        }];
    }
    

    现在您可以使用 _playerAliases 字典来查找玩家 ID 的昵称。由于您从加载分数的完成处理程序中调用loadPlayerData:,所有数据loadPlayersForIdentifiers: 完成后准备就绪。因此,这是触发表格视图更新的好时机。

    【讨论】:

    • 我仍然对您将如何重组它感到有些困惑。我已经更新了上面的问题,以显示我是如何调用/实现它的。
    【解决方案2】:

    请将此演示用于集成游戏中心 https://github.com/nihalahmed/GameCenterManager

    【讨论】:

      【解决方案3】:

      嗨!它对我有用。

      这是我的代码:

      GKLeaderboard *leaderboardRequest = [[GKLeaderboard alloc] init];
      
      leaderboardRequest.identifier = kHighScoreLeaderboardCategory;
      
      
      
      [leaderboardRequest loadScoresWithCompletionHandler:^(NSArray *scores, NSError *error)
      
       {
      
      if (error) {
      
      
      
      
      NSLog(@"%@", error);
              } 
      
      else if (scores) 
      {
      
              for (GKScore *s in scores)
      
              {
                  NSLog(@"Local player name is : %@", s.player.alias);
      
                   NSLog(@"Local player score's: %@", s.formattedValue);
      
      
              }
      
          }
      }];
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2020-09-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多