How to list all available GKTurnBasedMatches for a player?
Asked Answered
P

2

5

I'm building a game using Game Center's turn based matches.

I want to display a list of all the available matches. I've tried using loadMatchesWithCompletionHandler(), but the array of games returns as nil, and the error also returns as nil. There are some ongoing matches.

This is what I have so far:

func authenticateLocalUser() {
    if !gameCenterAvailable { return }

    let player = GKLocalPlayer.localPlayer()
    if player.authenticated == false {
        player.authenticateHandler = {(viewController, error) -> Void in
            if viewController != nil && self.presentingViewController != nil
            {
                self.presentingViewController!.presentViewController(viewController!, animated: true, completion: {
                    GKLocalPlayer.localPlayer().registerListener(self)

                    GKTurnBasedMatch.loadMatchesWithCompletionHandler({games, error in
                        print(games)
                        if games != nil {
                            print(games!.count)
                        }else {
                            print(error)
                        }
                    })
                })
            } else {

                if player.authenticated == true {
                    GKLocalPlayer.localPlayer().registerListener(self)

                    GKTurnBasedMatch.loadMatchesWithCompletionHandler({games, error in
                        print(games)
                        if games != nil {
                            print(games!.count)
                        }else {
                            print(error)
                        }
                    })
                }
            }
        }
    } else {
        print("already authenticated")
    }
}

I even get nil when creating a new match (it will print the match I just created, though):

func findMatchWith(minPlayers: Int, maxPlayers: Int) {
    if !gameCenterAvailable { return }

    let request = GKMatchRequest()
    request.minPlayers = minPlayers
    request.maxPlayers = maxPlayers
    request.defaultNumberOfPlayers = 2

    GKLocalPlayer.localPlayer().loadFriendPlayersWithCompletionHandler({players, error in
        if error != nil {return}
        request.recipients?.append(players![0])

        GKTurnBasedMatch.findMatchForRequest(request, withCompletionHandler: { match, error in
            if error != nil {
                print(error?.localizedDescription)
                return
            }
            print(match)

            GKTurnBasedMatch.loadMatchesWithCompletionHandler({games, error in
                print(games)
                if games != nil {
                    print(games!.count)
                }else {
                    print(error?.localizedDescription)
                } 
            })
        })
    })
}
Pitre answered 11/5, 2016 at 20:12 Comment(0)
P
2

It wasn't the code. It was how the game was set up in iTunes Connect. I needed to do this:

  1. Go to My App > App Store > Prepare for submission and toggle the switch for Game Center
  2. Add a leaderboard I had previously created under "Features"

Later, I will try to delete the leaderboard, and see if it still works. The actual app won't have a leaderboard.

My confusion was because I wasn't getting the "unrecognized game" error, and I was able to create matches, play turns, list player's friends, but not list matches.

Pitre answered 19/5, 2016 at 16:26 Comment(2)
Can you clarify this for me a little bit? Are you talking about available matches across the board, among all players with matches, everywhere? From the documentation it appeared to me that loadMatchesWithCompletionHandler only returned matches the player was already a member of, and there was no way to retrieve globally-available matches.Joubert
@LeMotJuiced It was matches the user is currently participating in.Pitre
R
0

It's a little hard to tell from the snippet you've shown. Things to double check:

  1. Where are you creating matches? You probably already know this, but just in case: loadMatchesWithCompletionHandler shows the matches that you've created, been invited to, or joined. It does not show all matches out there waiting for players.
  2. The completion handler for presenting the login view controller will never successfully load any matches. That completion handler will fire as soon as the login view controller is successfully displayed. It does not wait until you've actually submitted login credentials. So that attempt to load matches will occur before you're authenticated and will always return null.
  3. Your completion handler will get called in two circumstances. It occurs once when you set the completion handler, as you would expect. It will be called again after the login view controller (if displayed) finishes executing. On the second instance, you could get errors if the user canceled or failed login. Or, you will appear to be an authenticated, logged in user with no VC.
  4. You've got a few assumptions in your authentication chain that won't always work out:

You assume if .authenticated is YES then you are logged in. Unfortunately, that's not always true. GC will report YES in conditions where it can't talk to GC servers but is using cached data from a prior session. (Usually, though, you'll actually get an error about not being authenticated when you attempt to load matches while in this state)

You assume if the VC is nil, then you are authenticated. That's not always true, either. If an error is set, the VC will also be nil. Always check the value of the error first thing in the authentication handler. (I don't think this contributes to your problem now, though, because again: you should get an error if you try to load matches when you're actually not authenticated)

If you're interested, you can see an example of my authentication handler, which catches a variety of edge cases and failures, at https://mcmap.net/q/590536/-what-is-the-proper-way-to-do-gamecenter-authentication

Rosaline answered 14/5, 2016 at 18:38 Comment(9)
Thanks. I thought, as you suggested, that perhaps I was trying to get the matches before authentication finished, so I created a button and waited until the "Welcome back X" message went away to click it, but still nothing. I'll give that code a try.Pitre
I changed my authenticateHandler, as you suggested, and still nothing. I even create a new match in the app (not GC), then click the button to load matches, and still get nil. I did try to load matches before authentication, just to test, and I do get an error for that.Pitre
I initially deleted this comment based on your second comment; however, it might still be a good test: have you tried loading matches from within didFindMatch? If you get to didFindMatch then you have to be authenticated and you had to have successfully produced a match. I'd call loadMatchesWithCompletionHandler right inside didFindMatch and put a breakpoint inside the completion handler to check what you received.Rosaline
Still nil. I added the code I have for didFindMatch in my original question.Pitre
Another suggestion: temporarily comment out request.recipients?.append(players![0]) when you're creating the match and see what happens. That's the only thing I see different from what I do, which works (albeit in Obj-c rather than swift).Rosaline
I finally was able to make it work! I ended up adding a leaderboard, even though I don't need it, to force Game Center to recognize the app. It weird that Game Center sort of recognizes the app to the point that I can create games, play, but won't list available games. Thanks for the help.Pitre
Ah! that damn "you must have a leaderboard" thing. I didn't think of that because it didn;t throw the "unrecognized game" error. I'm going to edit the answer at #34056258 to indicate it fails silently sometimes too.Rosaline
I would get that error once in a while, but if I just waited a bit, it would go away. Very annoying. I'll check your edit to that answer. It's a great resource.Pitre
Whoops, I meant to link to this answer: https://mcmap.net/q/569797/-ios9-this-game-is-not-recognized-by-game-center (too late to edit the prior comment now)Rosaline

© 2022 - 2024 — McMap. All rights reserved.