在场景之间转换时保留循环故障

时间:2017-02-03 00:06:54

标签: swift transition retain skscene

我有一个游戏,其中主菜单呈现游戏场景,当玩家输掉时,游戏场景呈现菜单。从菜单转换到游戏场景时,菜单的 deinit 成功调用。我的问题是相反的情况不会发生(当从游戏场景转换到菜单场景时,不会调用gameScene的 deinit )。

我怀疑在我创建的新主菜单实例和创建实例的游戏场景之间存在一个强大的引用循环。事实很重要,如果我按照以下方式编辑我的gameScene代码,我会得到 deinit 的调用,但我的应用程序在运行时会在尝试呈现场景时崩溃:

class GameScene: SKScene {
    // Some stuff

    // Now the function which is called when I want to present back the menu scene:
    func lose() {
        // Some stuff

        // Delay is a helper function
        delay(bySeconds: 2.0, closure: { [unowned self] in
            for child in self.children {
                child.removeFromParent()
            }

            unowned let menu = MainMenu(size: CGSize(width: 1152, height: 2048))
            let reveal = SKTransition.fade(with: SKColor.black, duration: 1.0)

            self.view?.presentScene(menu, transition: reveal)
        })

    }
}

在运行时,我收到以下错误:

  

尝试保留已取消分配的对象

这是延迟的定义:

public func delay(bySeconds seconds: Double, dispatchLevel: DispatchLevel = .main, closure: @escaping () -> Void) {
    let dispatchTime = DispatchTime.now() + seconds
    dispatchLevel.dispatchQueue.asyncAfter(deadline: dispatchTime, execute: closure)
}

public enum DispatchLevel {
    case main, userInteractive, userInitiated, utility, background
    var dispatchQueue: DispatchQueue {
        switch self {
        case .main:                 return DispatchQueue.main
        case .userInteractive:      return DispatchQueue.global(qos: .userInteractive)
        case .userInitiated:        return DispatchQueue.global(qos: .userInitiated)
        case .utility:              return DispatchQueue.global(qos: .utility)
        case .background:           return DispatchQueue.global(qos: .background)
        }
    }
}

这是我的MainMenu课程:

class MainMenu: SKScene {
    let gameScene = GameScene(size: CGSize(width: 1152, height: 2048))
    let reveal = SKTransition.fade(with: SKColor.black, duration: 1.0)
    // Some stuff
    // override func didMove(to ...

    // Now the function which is called when I want to present the game scene:
    func presentGame() {
        view?.presentScene(gameScene, transition: reveal)
    }
}

我尝试了不同的东西,但是没有成功(例如:在gameScene的init方法中设置新的菜单实例)。

如果我删除了GameScene类中菜单常量的“无主”“定义,则转换成功,但不会调用 deinit

有什么建议吗?

1 个答案:

答案 0 :(得分:0)

我终于找到了保持我的游戏场景不被取消初始化的原因。

它与我在问题中提供的代码无关。问题出在一个强大的自我"在封闭内部引用,负责解释加速度计的输入。

如果您对更多信息感兴趣,请参阅此处:Retain cycle suspected in closure