Свифт - GKMatchDelegate
Я новичок в Swift, недавно начал разрабатывать собственное приложение. Я пытался реализовать многопользовательский Game Center. Текущая структура моего проекта (стандартная структура игрового центра):
- GameViewController - UIViewController, GKGameCenterControllerDelegate
- GameKitHelper - NSObject, GKGameCenterControllerDelegate, GKMatchmakerViewControllerDelegate, GKMatchDelegate
- GameKitHelperDelegate - протокол (matchStarted, matchEnded, match)
- MultiplayerNetwork - GameKitHelperDelegate (используется для отправки и обработки сообщений)
Проблема, с которой я сталкиваюсь, связана с очень ранними этапами создания многопользовательских игр. На GameViewController у меня есть следующий код для запуска многопользовательской игры:
func playMultiGame(){
var gameScene = GameSceneMultiPlayer(size:CGSize(width: 2048, height: 1536))
let networkingEngine = MultiplayerNetworking()
networkingEngine.delegate = gameScene
gameScene.networkingEngine = networkingEngine
GameKitHelper.SharedGameKitHelperInstance.findMatchWithMinPlayers(minPlayers: 2, maxPlayers: 2, viewController: self, delegate: networkingEngine)
let skView = self.view as! SKView
gameScene.scaleMode = .fill
skView.presentScene(gameScene)
}
Метод findMatchWithMinPlayers, запущенный выше, выглядит следующим образом:
func findMatchWithMinPlayers(minPlayers:Int, maxPlayers:Int, viewController:UIViewController, delegate:GameKitHelperDelegate) {
if(!_enableGameCenter) {
return;
}
_matchStarted = false
self._match = nil
_delegate = delegate
viewController.dismiss(animated: false, completion: nil)
//GKmatch request
let request = GKMatchRequest()
request.minPlayers = minPlayers
request.maxPlayers = maxPlayers
let mmvc = GKMatchmakerViewController(matchRequest: request)
mmvc?.matchmakerDelegate = self
viewController.present(mmvc!, animated: true, completion: nil)
}
Вышеуказанный метод находится в GameKitHelper, который имеет следующие методы:
class GameKitHelper : NSObject, GKGameCenterControllerDelegate, GKMatchmakerViewControllerDelegate, GKMatchDelegate {
var _enableGameCenter : Bool
var _matchStarted : Bool
var _match : GKMatch!
var _delegate : GameKitHelperDelegate?
var authenticationViewController: UIViewController?
var lastError : NSError?
var playersDict : NSMutableDictionary?
class var SharedGameKitHelperIntance:GameKitHelper {
return _GameKitHelperSharedInstace
}
override init() {
self._enableGameCenter = true
self._matchStarted = false
super.init()
}
func authenticateLocalPlayer() {
[...]
}
func setAuthenticationViewController(authViewController:UIViewController!) {
[...]
}
func findMatchWithMinPlayers(minPlayers:Int, maxPlayers:Int, viewController:UIViewController, delegate:GameKitHelperDelegate) {
[...]
}
func lookupPlayers() {
[...]
}
/* Implementing delegate GKMatchmakerViewControllerDelegate methods */
func matchmakerViewControllerWasCancelled(_ viewController:GKMatchmakerViewController) {
viewController.dismiss(animated: true, completion: nil)
print("canceling multiplayer view")
_delegate?.matchEnded()
}
func matchmakerViewController(_ viewController: GKMatchmakerViewController,
didFailWithError error: Error) {
viewController.dismiss(animated: true, completion: nil)
NSLog("Error finding match: %@", error.localizedDescription)
}
func matchmakerViewController(_ viewController: GKMatchmakerViewController,
didFind match: GKMatch!) {
viewController.dismiss(animated: true, completion: nil)
match.delegate = self
_match = match
if(!_matchStarted && match.expectedPlayerCount==0) {
NSLog("Ready to start match")
self.lookupPlayers()
}
}
/* Implementing delegate GKMatchDelegate methods */
func match(match: GKMatch!, didReceiveData data: NSData!, fromPlayer playerID: NSString!) {
if(_match != match) {
return
}
_delegate?.match(match: match, didReceiveData: data, fromPlayer: playerID)
}
func match(match: GKMatch!, player: String!, didChangeState state: GKPlayerConnectionState) {
if(_match != match) {
return
}
switch(state) {
case GKPlayerConnectionState.stateConnected:
if(!_matchStarted && match.expectedPlayerCount == 0) {
NSLog("Ready to start match!")
self.lookupPlayers()
}
case GKPlayerConnectionState.stateDisconnected:
NSLog("Player disconnected!")
_matchStarted = false
_delegate?.matchEnded()
default:
break
}
}
func match(match: GKMatch!, connectionWithPlayerFailed:String!, withError error:NSError!) {
if(_match != match) {
return
}
NSLog("Failed to connect to player with error: %@", error.localizedDescription)
_matchStarted = false
_delegate?.matchEnded()
}
func match(match: GKMatch!, didFailWithError error: NSError!) {
if(_match != match) {
return
}
NSLog("Match failed with error: %@", error.localizedDescription)
_matchStarted = false
_delegate?.matchEnded()
}
func gameCenterViewControllerDidFinish(_ gameCenterViewController: GKGameCenterViewController)
{
gameCenterViewController.dismiss(animated: true, completion: nil)
}
Как только два пользователя соединились, и игра готова к запуску, как только GKMatchmakerViewController был закрыт, приложение завершает работу в методе matchmakerViewController, который выполняет это действие:
func matchmakerViewController(_ viewController: GKMatchmakerViewController,
didFind match: GKMatch!) {
viewController.dismiss(animated: true, completion: nil)
_match.delegate = self
_match = match
if(!_matchStarted && match.expectedPlayerCount==0) {
NSLog("Ready to start match")
self.lookupPlayers()
}
}
Через точку останова исключения я заметил, что точная строка, которая вызывает проблему выше, является следующей:
_match.delegate = self
Я получаю следующую ошибку:
2017-07-12 19: 15: 47.472473 + 0100 xxx [2653: 492023] - [xxx.GameKitHelper match: didReceiveData: fromPlayer:]: нераспознанный селектор отправлен в экземпляр 0x17047a600 2017-07-12 19:15:47.507642+0100 xxx[2653:492023] *** Завершение работы приложения из-за необработанного исключения "NSInvalidArgumentException", причина: '-[xxx.GameKitHelper match:didReceiveData:fromPlayer:]: нераспознанный селектор, отправленный экземпляру 0x17047a600'
Есть идеи, что может быть причиной этой проблемы? Я перепробовал все.