Swift GameKit:与插件的连接在使用中中断
我已经试着解决这个问题好几个星期了。苹果开发者论坛没有回应。苹果开发人员的技术支持没有真正的帮助。考虑到我的项目中出现问题的可能性很高,我不能相信没有人解决过这个问题。无论如何,这是我的GameKitManager类:Swift GameKit:与插件的连接在使用中中断,swift,gamekit,Swift,Gamekit,我已经试着解决这个问题好几个星期了。苹果开发者论坛没有回应。苹果开发人员的技术支持没有真正的帮助。考虑到我的项目中出现问题的可能性很高,我不能相信没有人解决过这个问题。无论如何,这是我的GameKitManager类: final class GameCenterManager : NSObject, GKLocalPlayerListener { static let manager = GameCenterManager() weak var delegate: G
final class GameCenterManager : NSObject, GKLocalPlayerListener {
static let manager = GameCenterManager()
weak var delegate: GameCenterManagerDelegate?
var gameCenterViewController: UIViewController?
var match: GKMatch?
static var isAuthenticated: Bool {
return GKLocalPlayer.local.isAuthenticated
}
var matchmakerViewController: GKMatchmakerViewController?
var invite: GKInvite?
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 = 4
request.inviteMessage = "Would you like to play?"
matchmakerViewController = GKMatchmakerViewController(matchRequest: request)
matchmakerViewController!.matchmakerDelegate = self
delegate?.presentMatchmaking(viewController: matchmakerViewController)
}
func player(_ player: GKPlayer, didAccept invite: GKInvite) {
self.invite = invite
// Start match making 4 seconds after to let the invitation sliding menu to finish loading
let seconds = 4.0
DispatchQueue.main.asyncAfter(deadline: .now() + seconds) {
self.makeMatchmakerVC(from: invite)
}
}
func makeMatchmakerVC(from invite:GKInvite) {
// Accepting invitation from GKMatchmakerViewController (Friends are displayed)
if matchmakerViewController != nil {
matchmakerViewController!.dismiss(animated: true, completion: {
self.matchmakerViewController = GKMatchmakerViewController(invite: invite)
self.matchmakerViewController!.matchmakerDelegate = self
self.delegate?.presentMatchmaking(viewController: self.matchmakerViewController!)
})
}
// Accepting invitation when GKMatchmakerViewController is not yet presented
else {
guard let vc = GKMatchmakerViewController(invite: invite) else { return }
self.matchmakerViewController = vc
matchmakerViewController!.matchmakerDelegate = self
delegate?.presentMatchmaking(viewController: matchmakerViewController!)
}
}
}
extension GameCenterManager: GKMatchmakerViewControllerDelegate {
func matchmakerViewController(_ viewController: GKMatchmakerViewController, didFind match: GKMatch) {
print("-----matchmakerVC did find match-------")
viewController.dismiss(animated: true, completion: {
self.match = match
self.match!.delegate = self
self.delegate?.presentGame(match: self.match!)
})
}
func matchmakerViewControllerWasCancelled(_ viewController: GKMatchmakerViewController) {
viewController.dismiss(animated: true)
delegate?.matchmakingCancelled()
}
func matchmakerViewController(_ viewController: GKMatchmakerViewController,
didFailWithError error: Error)
{
viewController.dismiss(animated: true, completion: {
print("################# fail with error ##################\n\(error.localizedDescription)\n")
self.matchmakerViewController!.matchmakerDelegate = nil
self.matchmakerViewController = nil
self.invite = nil
self.match = nil
})
}
}
最终类GameCenterManager:NSObject,GKLocalPlayerListener{
静态let管理器=GameCenterManager()
弱var委托:GameCenterManagerDelegate?
var gameCenterViewController:UIViewController?
变量匹配:GKMatch?
静态变量已验证:Bool{
返回GKLocalPlayer.local.isAuthenticated
}
var matchmakerViewController:GKMatchmakerViewController?
var invite:GKIVITE?
重写init(){
super.init()
}
func authenticatePlayer(){
GKLocalPlayer.local.authenticateHandler={gcAuthVC,中出现错误
self.delegate?.didChangeAuthStatus(isAuthenticated:GKLocalPlayer.local.isAuthenticated)
如果GKLocalPlayer.local.isAuthenticated{
GKLocalPlayer.local.register(self)
}
//如果用户需要登录游戏中心
否则,如果让vc=gcAuthVC{
self.delegate?.presentGameCenterAuth(视图控制器:vc)
}
否则{
打印(“>>>验证播放器时出错!\”(错误?.localizedDescription???“无”)如果有人遇到相同的问题,以下操作是否有帮助
func player(_ player: GKPlayer, didAccept invite: GKInvite) {
if matchmakerViewController != nil {
matchmakerViewController!.dismiss(animated: false, completion: nil)
self.matchmakerViewController!.matchmakerDelegate = nil
self.matchmakerViewController = nil
}
let delayTime = DispatchTime.now() + .milliseconds(2000)
DispatchQueue.main.asyncAfter(deadline: delayTime) {
self.matchmakerViewController = GKMatchmakerViewController(invite: invite)
self.matchmakerViewController!.matchmakerDelegate = self
self.delegate?.presentMatchmaking(viewController: self.matchmakerViewController!)
}
}
Dispatch.asyncAfter让系统有时间在开始新任务之前对matchmakerViewController进行全面“清理”。我现在正在测试它,但其他人的反馈将不胜感激
编辑:
经过更多的测试,这并不是解决方案;问题还在继续。但是,我注意到,当第二个玩家打开了GKMatchmakerViewController实例时,我没有问题。换句话说,如果我调用presentMatchmaker()
首先,然后接受邀请,它会起作用。因此,例如,当第二个玩家不在游戏中并收到游戏邀请时,就会出现问题。因此,我将代码更改为以下代码,到目前为止似乎有效:
public func player(_ player: GKPlayer, didAccept invite: GKInvite) {
if matchmakerViewController != nil {
matchmakerViewController!.dismiss(animated: false, completion: nil)
self.matchmakerViewController!.matchmakerDelegate = nil
self.matchmakerViewController = nil
}
// THIS HELPS AVOID CRASH.
presentMatchmaker()
let delayTime = DispatchTime.now() + .milliseconds(1000)
DispatchQueue.main.asyncAfter(deadline: delayTime) {
self.matchmakerViewController = GKMatchmakerViewController(invite: invite)
self.matchmakerViewController!.matchmakerDelegate = self
self.delegate?.presentMatchmaking(viewController: self.matchmakerViewController!)
}
}
这不是一个非常优雅的解决方案…当错误发生时,我发现了另一个用例。玩家1邀请玩家2玩游戏,玩家2接受邀请。然后任何一个玩家停止比赛(比赛被取消,现在两个都为零:GameCenterManager.manager.match.disconnect();GameCenterManager.manager.match=nil
)。然后,玩家2邀请玩家1,玩家1接受另一场比赛的邀请。玩家2找到比赛并进入游戏场景,而玩家1最终出现此错误(接受邀请,然后无法创建新比赛)。如果其他人遇到此问题,我发现创建和显示GKMatchmakerViewController
,然后在DispatchQueue.main.asyncAfter(截止日期:.now())中设置委托
也解决了这个问题。这仍然是一个黑客攻击,但似乎更干净,因为不需要额外的视图控制器,也没有延迟。谢谢。正如您在我的最后一段代码中看到的,这就是我所做的。如果不调用presentMatchmaker()
,仍然存在相同的问题。干杯。