Reputation: 712
According to Apple's documentation, you should set GKLocalPlayer.local.authenticateHandler
, once at app launch, with a closure that accepts a viewController
and an error
. And if the viewController
is not nil
, you should save it and present it to the user at the appropriate time.
I copy/pasted their example to my own app, and the behavior I see is completely different.
Instead of giving me a view controller to present later, immediately after setting the closure, the standard Game Center UI is presented. At this point my closure is not yet called. Then, after either logging in or tapping "Cancel", the Game Center UI is dismissed. At this point the closure is called. error
correctly reflects whether the user logged in. But in either case viewController
is always nil
.
If I restart the app after tapping "Cancel", the system seems to remember that I cancelled. Then the UI is not presented, and the closure is called with viewController
still being nil
and error
being non-nil
.
This behavior is undesirable to me for a couple reasons:
For context, I am setting the closure in a top-level SwiftUI view like this:
struct ActiveGamesView: View {
@State private var isPresentingAuth = false
@State private var gameCenterAuthVC: UIViewController?
@State private var gameCenterEnabled = false
@State private var isMultiplayerGamingRestricted = true
@State private var isPersonalizedCommunicationRestricted = true
var body: some View {
NavigationView {
VStack {
Spacer()
NavigationLink(destination: Text("This is the online play area")) {
Text("Play Online")
}
}
}
.onAppear() {
authenticateGameCenter()
}
.fullScreenCover(isPresented: $isPresentingAuth) {
GameCenterAuthView(underlyingViewController: gameCenterAuthVC!)
// This is a UIViewControllerRepresentable that just presents gameCenterAuthVC.
}
}
private func authenticateGameCenter() {
gameCenterAuthVC = viewController
isPresentingAuth = viewController != nil
gameCenterEnabled = error == nil
isMultiplayerGamingRestricted = GKLocalPlayer.local.isMultiplayerGamingRestricted
isPersonalizedCommunicationRestricted = GKLocalPlayer.local.isPersonalizedCommunicationRestricted
}
}
As expected given the current unexpected behavior, my fullScreenCover
closure never gets called, so my saved gameCenterAuthVC
never gets presented.
My question is: is this auto-presenting UI normal, and Apple just didn't update their docs? Or am I doing something wrong?
Upvotes: 5
Views: 636
Reputation: 1339
yes i've also thought that the apple docs are confusing on this point ("Present the view controller so the player can sign in.") i don't think you need to (or can?) "capture" the viewController and save it for later. so when/if you want to log in to Game Center you call the following
GKLocalPlayer.local.authenticateHandler = { viewController, error in
}
this need not happen at app launch. and the authenticateHandler
closure can be empty.
Upvotes: 2