SwiftUI Game Center authentication doesn't prompt user to login

831 views Asked by At

I have the below code to authenticate a local player in Game Center in my SwiftUI app. I want Game Center to prompt user to login if the player is not already login in but this doesn't happen.

class AppSettings: UINavigationController {
    func authenticateUser() {
        let localPlayer = GKLocalPlayer.local
        localPlayer.authenticateHandler = { vc, error in
            guard error == nil else {
                print(error?.localizedDescription ?? "")
                return
            }
        }
    }
}

What could be the problem? I also read about using UIViewControllerRepresentable somewhere in my class to integrate UIKit's ViewController into SwiftUI but I don't understand how I can use it. Can someone help me out?

2

There are 2 answers

5
Heyman On BEST ANSWER

I didn't get anyone to answer my question correctly and after days of digging I found a solution. So I had to use the UIKit implementation like below and create a wrapper around it using UIViewControllerRepresentable in the GameCenterManager Struct. After that all I had to do was call GameCenterManager() inside my SwiftUI view in a ZStack and the job is done!

import SwiftUI
import UIKit
import GameKit


class ViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        authenticateUser()
    }
    let localPlayer = GKLocalPlayer.local
    func authenticateUser() {
        
        localPlayer.authenticateHandler = { vc, error in
            guard error == nil else {
                print(error?.localizedDescription ?? "")
                return
            }
            if vc != nil {
                self.present(vc!, animated: true, completion: nil)
            }
            if #available(iOS 14.0, *) {
                GKAccessPoint.shared.location = .bottomLeading
                GKAccessPoint.shared.showHighlights = true
                GKAccessPoint.shared.isActive = self.localPlayer.isAuthenticated
                
                // Fallback on earlier versions
            }
        }
    }
}


struct GameCenterManager: UIViewControllerRepresentable {
    
    func makeUIViewController(context: UIViewControllerRepresentableContext<GameCenterManager>) -> ViewController {
        
        
        let viewController = ViewController()
        return viewController
        
    }
    
    func updateUIViewController(_ uiViewController: ViewController, context: UIViewControllerRepresentableContext<GameCenterManager>) {
        
    }
    
}
1
pawello2222 On

The authenticateHandler returns a UIViewController as well which you're not using:

@available(iOS 6.0, *)
open var authenticateHandler: ((UIViewController?, Error?) -> Void)?

You need to present it:

class AppSettings: UINavigationController {
    func authenticateUser() {
        let localPlayer = GKLocalPlayer.local
        localPlayer.authenticateHandler = { vc, error in
            guard error == nil else {
                print(error?.localizedDescription ?? "")
                return
            }
            if let vc = vc {
                self.present(vc, animated: true, completion: nil)
            }
        }
    }
}