GKTurnBasedEventListener could not be set to delegate of my ViewController?
Asked Answered
S

2

2

In objC the syntax written by Rawendrich for GKTurnBasedEventListener, which was GKTurnBasedEventHandler there at that time, now changed by Apple is as below.

 if (!gameCenterAvailable) return;

void (^setGKEventHandlerDelegate)(NSError *) = ^ (NSError *error)
{
    GKTurnBasedEventHandler *ev = 
      [GKTurnBasedEventHandler sharedTurnBasedEventHandler];
    ev.delegate = self;
};

NSLog(@"Authenticating local user...");
if ([GKLocalPlayer localPlayer].authenticated == NO) {     
    [[GKLocalPlayer localPlayer] 
     authenticateWithCompletionHandler:
      setGKEventHandlerDelegate];        
} else {
    NSLog(@"Already authenticated!");
    setGKEventHandlerDelegate(nil);
}

Now after converting this to swift, and with the composition of writing down GKTurnBasedEventListener instead of GKTurnBasedEventHandler, this comes the following way.

//  Converted with Swiftify v1.0.6381 - https://objectivec2swift.com/
if !gameCenterAvailable {
return
}
var setGKEventHandlerDelegate: ((_: Error) -> Void)? = {(_ error:   Error?) -> Void in
    var ev = GKTurnBasedEventHandler.shared()
    ev.delegate = self
}
print("Authenticating local user...")
if GKLocalPlayer.localPlayer().authenticated == false {
GKLocalPlayer.localPlayer().authenticate(withCompletionHandler:    setGKEventHandlerDelegate)
}
else {
print("Already authenticated!")
setGKEventHandlerDelegate(nil)

}

Unfortunately this is not the right syntax to set delegate of GKTurnBasedEventListener for my ViewController.

Please if anyone of you could solve this for me, because without this I'm not able to read through event listener's default functions.

Cheers!

Salazar answered 3/7, 2017 at 15:13 Comment(0)
S
0

Finally after just about harsh 10 hours, I figured out this problem from Here. Although this syntax is in objC, but there's no problem of converting it to swift from Swiftify.

Although a bit later than the real time, but I'm now able to understand that setting delegate of GKTunBasedEventListener is not like the one we do for UITableViewControllerDelegate.

Here, one must have to first authenticate local player, then after you have to register local player's listener to the ViewController's delegate GKLocalPlayerListener.

One other thing I found on Apple's Documentation: Do not implement GKChallengeListener, GKInviteEventListener, GKSavedGameListener, and GKTurnBasedEventListener directly; implement GKLocalPlayerListener instead. You can listen for and handle multiple events using GKLocalPlayerListener.

So then on I've implemented in the following way.

import GameKit

class ViewController: UIViewController,   GKTurnBasedMatchmakerViewControllerDelegate, 
GKLocalPlayerListener {


..... 


func player(_ player: GKPlayer, receivedTurnEventFor match: GKTurnBasedMatch, didBecomeActive: Bool) {

    print("#1")
    print(player)
    print("#2")
    print(match)
    print("#3")
    print(didBecomeActive)

    if match.status == GKTurnBasedMatchStatus.open
    {
        if GKLocalPlayer.localPlayer() == match.currentParticipant
        {


        if didBecomeActive
        {
            // Active now
        }
        else
        {
            // Active already
        }

        }
        else
        {
            // It's someone's turn

            if match.matchData != myMatch?.matchData
            {
               // Match Data being Updated by Someone
                print(player.alias ?? "No Name:")
            }

        }


    }

    thirdTopLabel.text = match.matchID! + "\n" + didBecomeActive.description

}

.... 

Now in ViewDidLoad() function put the following code.

// In the ViewDidLoad function 
 if(!GKLocalPlayer.localPlayer().isAuthenticated)
    {
        authenticatePlayer { (auth) in

            weak var weakSelf = self
            weak var weakPlayer = GKLocalPlayer.localPlayer()

            if(auth){


                 weakPlayer?.register(weakSelf!)
                 self.suthentication = true;

            }
            else{
                print("failed in authentication")
                self.suthentication = false;
            }

        }

    }
    else
    {
        // Already Authenticated
        GKLocalPlayer.localPlayer().register(self)
        localPlayer = GKLocalPlayer.localPlayer()


    }

And finally your Authentication function should be like this.

// authenticate local player :: Just Authentication
func authenticatePlayer(completionHandler: @escaping (_ resultedPlaces: Bool) -> Void) {

    localPlayer = GKLocalPlayer.localPlayer()


    localPlayer.authenticateHandler =
        { (viewController , error ) -> Void in
            if viewController != nil
            {
                self.present(viewController!, animated:true, completion: nil)
            }
            else
            {
                if self.localPlayer.isAuthenticated
                {

                    completionHandler(true);
                }
                else
                {
                    completionHandler(false);


                    print("not able to authenticate fail")
                    self.gameCenterEnabled = false

                    if (error != nil)
                    {
                        print("\(error.debugDescription)")
                    }
                    else
                    {
                        print(    "error is nil")
                    }
                }
            }

    }
}

NOTE: GKLocalPlayerListener won't work on simulator.

Salazar answered 4/7, 2017 at 6:24 Comment(0)
G
2

FYI, if you want a working example of how to use GKLocalPlayerListener during a turn-based GameKit match, you are welcome to take a look at this example project for a turn based game. I hope it helps to see all the pieces in context.

Glyptodont answered 27/7, 2017 at 22:21 Comment(0)
S
0

Finally after just about harsh 10 hours, I figured out this problem from Here. Although this syntax is in objC, but there's no problem of converting it to swift from Swiftify.

Although a bit later than the real time, but I'm now able to understand that setting delegate of GKTunBasedEventListener is not like the one we do for UITableViewControllerDelegate.

Here, one must have to first authenticate local player, then after you have to register local player's listener to the ViewController's delegate GKLocalPlayerListener.

One other thing I found on Apple's Documentation: Do not implement GKChallengeListener, GKInviteEventListener, GKSavedGameListener, and GKTurnBasedEventListener directly; implement GKLocalPlayerListener instead. You can listen for and handle multiple events using GKLocalPlayerListener.

So then on I've implemented in the following way.

import GameKit

class ViewController: UIViewController,   GKTurnBasedMatchmakerViewControllerDelegate, 
GKLocalPlayerListener {


..... 


func player(_ player: GKPlayer, receivedTurnEventFor match: GKTurnBasedMatch, didBecomeActive: Bool) {

    print("#1")
    print(player)
    print("#2")
    print(match)
    print("#3")
    print(didBecomeActive)

    if match.status == GKTurnBasedMatchStatus.open
    {
        if GKLocalPlayer.localPlayer() == match.currentParticipant
        {


        if didBecomeActive
        {
            // Active now
        }
        else
        {
            // Active already
        }

        }
        else
        {
            // It's someone's turn

            if match.matchData != myMatch?.matchData
            {
               // Match Data being Updated by Someone
                print(player.alias ?? "No Name:")
            }

        }


    }

    thirdTopLabel.text = match.matchID! + "\n" + didBecomeActive.description

}

.... 

Now in ViewDidLoad() function put the following code.

// In the ViewDidLoad function 
 if(!GKLocalPlayer.localPlayer().isAuthenticated)
    {
        authenticatePlayer { (auth) in

            weak var weakSelf = self
            weak var weakPlayer = GKLocalPlayer.localPlayer()

            if(auth){


                 weakPlayer?.register(weakSelf!)
                 self.suthentication = true;

            }
            else{
                print("failed in authentication")
                self.suthentication = false;
            }

        }

    }
    else
    {
        // Already Authenticated
        GKLocalPlayer.localPlayer().register(self)
        localPlayer = GKLocalPlayer.localPlayer()


    }

And finally your Authentication function should be like this.

// authenticate local player :: Just Authentication
func authenticatePlayer(completionHandler: @escaping (_ resultedPlaces: Bool) -> Void) {

    localPlayer = GKLocalPlayer.localPlayer()


    localPlayer.authenticateHandler =
        { (viewController , error ) -> Void in
            if viewController != nil
            {
                self.present(viewController!, animated:true, completion: nil)
            }
            else
            {
                if self.localPlayer.isAuthenticated
                {

                    completionHandler(true);
                }
                else
                {
                    completionHandler(false);


                    print("not able to authenticate fail")
                    self.gameCenterEnabled = false

                    if (error != nil)
                    {
                        print("\(error.debugDescription)")
                    }
                    else
                    {
                        print(    "error is nil")
                    }
                }
            }

    }
}

NOTE: GKLocalPlayerListener won't work on simulator.

Salazar answered 4/7, 2017 at 6:24 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.