I am trying to implement a real-time match in GameCenter using GameKit and SpriteKit.
This is my scene:
class IntroScene: SKScene, GameCenterManagerDelegate {
	var gameCenterManager: GameCenterManager?
	override func didMove(to view: SKView) {
		GameCenterManager.manager.delegate = self
		<other code>
	}
	override func didChangeSize(_ oldSize: CGSize) {
		super.didChangeSize(oldSize)
		GameCenterManager.manager.authenticatePlayer()
	}
	func didChangeAuthStatus(isAuthenticated: Bool) {
		...Enabling the Button to play in GameCenter
	}
	func presentGameCenterAuth(viewController: UIViewController?) {
		guard let vc = viewController else {return}
		self.view!.window?.rootViewController?.present(vc, animated: true)
	}
	func presentMatchmaking(viewController: UIViewController?) {
		guard let vc = viewController else {return}
		self.view!.window?.rootViewController?.present(vc, animated: true)
	}
	->> Problem here. Never gets called
	func presentGame(match: GKMatch) {
		print("....INTROSCENE: DELEGATE PRESENT_GAME CALLED......")
		... Presenting a new scene
	}
}
This is my GameCenterManager class:
final class GameCenterManager : NSObject, GKLocalPlayerListener {
static let manager = GameCenterManager()
weak var delegate: GameCenterManagerDelegate?
var maxPlayers = 2
var match: GKMatch?
static var isAuthenticated: Bool {
return GKLocalPlayer.local.isAuthenticated
}
override init() {
super.init()
}
func authenticatePlayer() {
GKLocalPlayer.local.authenticateHandler = { gcAuthVC, error in
self.delegate?.didChangeAuthStatus(isAuthenticated: GKLocalPlayer.local.isAuthenticated)
if GKLocalPlayer.local.isAuthenticated {
GKLocalPlayer.local.register(self)
}
// If the User needs to sign to the Game Center
else if let vc = gcAuthVC {
self.delegate?.presentGameCenterAuth(viewController: vc)
}
else {
print(">>>>> Error authenticating the Player! \(error?.localizedDescription ?? "none") <<<<<")
}
}
}
func presentMatchmaker() {
guard GKLocalPlayer.local.isAuthenticated else { return }
let request = GKMatchRequest()
request.minPlayers = 2
request.maxPlayers = 6
request.inviteMessage = "Would you like to play?"
guard let vc = GKMatchmakerViewController(matchRequest: request) else { return }
vc.matchmakerDelegate = self
delegate?.presentMatchmaking(viewController: vc)
}
	// THIS IS WORKING...
func player(_ player: GKPlayer, didAccept invite: GKInvite) {
print("-----player -- did accept invite-------\(player.displayName)")
guard let vc = GKMatchmakerViewController(invite: invite) else { return }
vc.matchmakerDelegate = self
self.gameCenterViewController?.present(vc, animated: true, completion: nil)
}
func player(_ player: GKPlayer, didRequestMatchWithRecipients recipientPlayers: [GKPlayer]) {
print("didRequestMatchWithRecipients")
}
func player(_ player: GKPlayer, matchEnded match: GKTurnBasedMatch) {
print("match ended")
}
func player(_ player: GKPlayer, wantsToQuitMatch match: GKTurnBasedMatch) {
print("wants to quit match")
}
}
extension GameCenterManager: GKMatchmakerViewControllerDelegate {
	// THIS IS NOT WORKING -(
func matchmakerViewController(_ viewController: GKMatchmakerViewController, didFind match: GKMatch) {
print("-----matchmakerVC did find match-------")
viewController.dismiss(animated: true)
match.delegate = self
delegate?.presentGame(match: match)
}
func matchmakerViewControllerWasCancelled(_ viewController: GKMatchmakerViewController) {
print("matchmakerVC was cancelled")
viewController.dismiss(animated: true)
delegate?.matchmakingCancelled()
}
func matchmakerViewController(_ viewController: GKMatchmakerViewController, didFailWithError error: Error) {
viewController.dismiss(animated: true)
delegate?.matchmakingError(error: error)
}
}
extension GameCenterManager: GKMatchDelegate {
func match(_ match: GKMatch, didReceive data: Data, forRecipient recipient: GKPlayer, fromRemotePlayer player: GKPlayer) {
// HANDLE DATA
}
func match(_ match: GKMatch, didReceive data: Data, fromRemotePlayer player: GKPlayer) {
//HANDLE DATA
}
func match(_ match: GKMatch, player: GKPlayer, didChange state: GKPlayerConnectionState) {
print("-----match did change state")
guard match == self.match else { return }
switch state {
case .connected where self.match != nil :
print("-----MATCH DID CHANGE STATE CONNECTED-----")
case .disconnected:
print("-----MATCH DID CHANGE STATE DISCONNECTED-----")
default:
break
}
}
func match(_ match: GKMatch, didFailWithError error: Error?) {
print("-----match did fail with error")
}
}
So, basically this is what happens. Player 1 starts the game. The player gets successfully authenticated.
I invite Player 2 to join the game. The invitation is sent to Player 2's device.
Player 2 accepts the game (printing player did accept invite).
However, after that nothing happens. There is continuing spinning wheel saying "Sending" on Player 1's device, and the game scene never launches. I never receive notification that the match has been found, i.e. matchmakerViewController(_ viewController:,match:) is never called.
Any help would be greatly appreciated!