编写苹果游戏中心应用程序(翻译 1.8 获取本地玩家的好友信息)

 

1.8 获取本地玩家的好友信息

问题

    你已添加好友到本地玩家账户,但现在想枚举这些好友并获得他们的信息,比如他们的别名。

解决方案

    使用本地玩家对象的friends属性。

讨论

    GKLocalPlayer有一个叫作friends的属性,为NSArray类型。该属性“将”包含本地玩家的好友;数组使用玩家ID(参考条目1.6)表示玩家。

    上面的段落中说的是“将”,这是因为在本地玩家通过身份验证后,该数组是空的(nil)。你需要调用GKLocalPlayer类的实例方法loadFriendsWithCompletionHandler:来加载该数组。取得ID后,调用另外一个方法获取每个好友的其它信息。

    GKLocalPlayer类的实例方法loadFriendsWithCompletionHandler:接受一个参数,该参数必须是一个返回void(换句话说,就是无返回值)并且拥有两个参数的块对象。块对象的第一个参数为NSArray类型,将返回本地玩家的好友ID。第二个参数为NSError类型,返回处理过程中是否有错误发生。

    为避免代码多次重复,此处假定本地玩家已经通过身份验证(参考条目1.5)。

    下面看看加载本地玩家好友ID的示例:

        void (^getLocalPlayerFriends)(void) = ^{

            GKLocalPlayer *localPlayer = [GKLocalPlayer localPlayer];

            if ([localPlayer isAuthenticated] == NO){
                NSLog(@"The local player is not authenticated.");
                return;
            }

            NSLog(@"Loading local player's friend IDs...");
            [localPlayer loadFriendsWithCompletionHandler:
            ^(NSArray *friends, NSError *error) {

                if (friends != nil){
                    NSLog(@"Successfully retrieved friends of the local player.");
                    NSUInteger counter = 1;
                    for (NSString *friendID in friends){
                        NSLog(@"Friend %lu = %@", (unsigned long)counter, friendID);
                        counter++;
                    }
                }

                if (error != nil){
                    NSLog(@"Error occurred. Error = %@", error);
                }
            }];

        };

    如条目1.2中的第一步所提,我创建了三个游戏中心的玩家,这样才能向你演示游戏中心的功能。如果你仅创建了一个玩家,就无法去做诸如添加好友之类的事情,除非你能确切地知道沙盒上的其它玩家。不过,我再次强烈建议,你至少创建两位玩家,以便测试本书中的示例代码。

    在iOS模拟器中运行该代码,获得类似如下的结果:

        Loading local player's friend IDs...
        Successfully retrieved friends of the local player.
        Friend 1 = G:1428629254
        Friend 1 = G:1428629742

    如你所见,我添加了两位好友。如果你再次查看代码,就会注意到我检查了好友数组是否为nil,然后在then中检查加载过程中是否有错误发生。这么作的原因很简单:游戏中心只是试图加载本地玩家好友。即使有错误发生,也可能已经加载了一些信息。因此,你获得的数组中包含了本地玩家的部分好友。虽然只有好友的一部分,但你可能仍想继续执行下去。如果你要确定没有错误发生,我建议你首先检查错误参数,然后再打印数组friends的内容。

    为侦测游戏中心是否能够成功加载好友列表,我们应当确保错误参数为nil;为侦测好友列表是否被部分接收,我们应当检查好友数组和错误参数是否都不是nil。如果有nil,则意味着,虽然我们可能获得了一些好友,但在获取其余好友时发生了错误。

    一切都进行得不错,我拥有了本地玩家的好友的ID。为使用玩家ID取得GKPlayer类的实例,你得使用GKPlayer类的类方法loadPlayersForIdentifiers:withCompletionHandler:,完整的流程如下:

    1. 验证本地玩家。

    2. 获取本地玩家的ID。

    3. 根据玩家ID获取GKPlayer的实例:

        void (^getLocalPlayerFriendsDetails)(void) = ^{

            GKLocalPlayer *localPlayer = [GKLocalPlayer localPlayer];

            if ([localPlayer isAuthenticated] == NO){
                NSLog(@"The local player is not authenticated.");
                return;
            }

            if ([[localPlayer friends] count] == 0){
                NSLog(@"The local player has no friends. How sad!");
                return;
            }

            NSLog(@"Loading players...");
            [GKPlayer
            loadPlayersForIdentifiers:[localPlayer friends]
            withCompletionHandler:^(NSArray *players, NSError *error) {

                if (players != nil){
                    NSLog(@"Successfully loaded the players.");
                    for (GKPlayer *player in players){
                        NSLog(@"%@", player);
                    }
                }

                if (error != nil){
                    NSLog(@"Error happened. Error = %@", error);
                }
            }];
        };

         void (^getLocalPlayerFriends)(void) = ^{

            GKLocalPlayer *localPlayer = [GKLocalPlayer localPlayer];

            if ([localPlayer isAuthenticated] == NO){
                NSLog(@"The local player is not authenticated.");
                return;
            }

            NSLog(@"Loading local player's friend IDs...");
            [localPlayer loadFriendsWithCompletionHandler:
            ^(NSArray *friends, NSError *error) {
                if (friends != nil){
                    NSLog(@"Successfully retrieved friends of the local player.");

                    dispatch_queue_t concurrentQueue =
                        dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
                    dispatch_async(concurrentQueue, getLocalPlayerFriendsDetails);
                }

                if (error != nil){
                    NSLog(@"Error occurred. Error = %@", error);
                }
            }];
        };

         - (void) authenticateLocalPlayerAndGetHerInfo{

            dispatch_queue_t concurrentQueue =
                dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

            dispatch_async(concurrentQueue, ^(void) {
                GKLocalPlayer *localPlayer = [GKLocalPlayer localPlayer];
                if ([localPlayer isAuthenticated] == NO){
                    [localPlayer authenticateWithCompletionHandler:^(NSError *error) {
                        if (error == nil){
                            NSLog(@"Successfully authenticated.");
                            dispatch_async(concurrentQueue, getLocalPlayerFriends);
                        } else {
                            NSLog(@"Failed to authenticate. Error = %@", error);
                        }
                    }];
                } else {
                    dispatch_async(concurrentQueue, getLocalPlayerFriends);
                }
            });
        }

    调用authenticateLocalPlayerAndGetHerInfo之后,我获得了如下的信息(因为我通过身份验证的本地玩家,拥有两个好友):

        Successfully authenticated.
        Loading local player's friend IDs...
        Successfully retrieved friends of the local player.
        Loading players...
        Successfully loaded the players.
        <GKPlayer 0x5f32d90>(playerID: G:1428629254, alias: Test Game User 2,
        status: (null), rid:(null))
        <GKPlayer 0x5f32cf0>(playerID: G:1428629742, alias: Test Game User 3,
        status: (null), rid:(null))

    拥有这些信息后,你可以将他们显示给玩家或持有在以后引用。不要将玩家ID保存在游戏中。无论玩家何时运行你的应用程序,你都必须重新获取好友列表,而不要假设几天前获取的好友仍然是本地玩家的好友。另外,玩家ID的格式也可能改变,正如Apple在其文档中所提:

        Do not make assumptions about the contents of the player identifier string. Its format and length are subject to change.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值