I have a working simple single player game, where the initial view controller has a button to start the game. This button performs a segue and all game logic in the GameViewController is working as expected.
I've followed this tutorial to add multi player functionality to my game. On the initial view controller, a button now calls
GameKitHelper.sharedGameKitHelper.findMatchWithMinPlayers(2, maxPlayers: 2, viewController: self, delegate: MultiPlayerNetworking)
}
which has the following implementation in GameKitHelper.swift:
func findMatchWithMinPlayers (minPlayers: Int, maxPlayers: Int, viewController: UIViewController, delegate: GameKitHelperDelegate) {
matchStarted = false
let request = GKMatchRequest()
self.delegate = delegate
request.minPlayers = 2
request.maxPlayers = 2
presentingViewController = viewController
presentingViewController.dismissViewControllerAnimated(false, completion: nil)
let mmvc = GKMatchmakerViewController(matchRequest: request)
mmvc?.matchmakerDelegate = self
presentingViewController.presentViewController(mmvc!, animated: true, completion: nil)
self.delegate?.matchStarted()
}
The Class MultiPlayerNetworking implements the GameKitHelper protocol, and gets called on the matchStarted function. The MultiPlayerNetworking class in essence takes over here, and starts sending out messages to hosts and remote players.
Note that some time later, When auto-matching finishes, the following function gets called in GameKitHelper:
func matchmakerViewController(viewController: GKMatchmakerViewController, didFindMatch match: GKMatch) {
viewcontroller.dismissViewControllerAnimated(true, completion: {})
self.match = match
match.delegate = self
}
Now, I think this says that the GKMatchmakerViewController is dismissed, thereby showing me the initial view controller again (and this is what happens on screen).
Now my issue! After the GKMatchmakerViewController is dismissed, I'm back at the initial view controller and want to 'simulate' an automatic segue to my gameView (which has logic to deal with a multi player game as well).
I've made the initial view controller conform to the MultiPlayerNetworking protocol, which has a function to simulate a segue:
func segueToGVC() {
self.performSegueWithIdentifier("game", sender: nil) // self = initial view controller
}
However, xCode complains with:
Warning: Attempt to present <GameViewController: 0x7d440050> on <GKMatchmakerViewController: 0x7c8fbc00> whose view is not in the window hierarchy!
I'm stuck here, and have tried so many different methods of dismissing the view controller, to making sure I'm calling the performSegue function on the topViewController via this link, but nothing works.
My question: why is the GKMatchmakerViewController visually dismissed, but still present in the view hierarchy, such that calling a performSegue function on the initial view controller give the above error/warning?
Views are greatly appreciated!
why is the GKMatchmakerViewController visually dismissed, but still present in the view hierarchy
Here are two suggestions:
Perhaps it's because dismissal takes time. You are saying:
viewcontroller.dismissViewControllerAnimated(true, completion: {})
So there's an animation. Don't attempt to perform the next segue until the animation is over.
Perhaps you are just wrong about who self
is. You are saying:
self.performSegueWithIdentifier("game", sender: nil)
// self = initial view controller
We have only your word, in that comment, for who self
is. Meanwhile, the runtime seems to think differently about the matter:
Attempt to present
<GameViewController: 0x7d440050>
on<GKMatchmakerViewController: 0x7c8fbc00>
It might be good to believe the runtime; after all, it knows more than you do.