NSNotificationCenter使用SpriteKit导致EXC_BAD_ACCESS错误

Tom*_*Tom 2 nsnotificationcenter ios sprite-kit swift

我正在使用NSNotificationCenter试图控制SpriteKit中的计时器.我第一次进入SKScene时代码运行正常,但是当我尝试重新进入SKScene时,我收到了EXC_BAD_ACCESS错误.我认为这与removeObserver函数有关.我不确定何时删除观察者,我试图在prepareForSegue函数中执行此操作但没有成功.我的viewController如下:

class JobStartedViewController: UIViewController {



var titleOfJob: String = ""

override func viewDidLoad() {
    super.viewDidLoad()

    let skView = self.view as! SKView

  let scene:SKScene = GameScene.init(size: skView.bounds.size)

    NSNotificationCenter.defaultCenter().postNotificationName("stopTimerNotification", object: nil)
    NSNotificationCenter.defaultCenter().postNotificationName("startTimerNotification", object: nil)

    /* Sprite Kit applies additional optimizations to improve rendering performance */
    skView.ignoresSiblingOrder = true

    /* Set the scale mode to scale to fit the window */
    scene.scaleMode = .AspectFill

    skView.presentScene(scene)
}
Run Code Online (Sandbox Code Playgroud)

我将观察者添加到我的GameScene.swift中,如下所示:

class GameScene: SKScene {   


override func didMoveToView(view: SKView) {


    NSNotificationCenter.defaultCenter().addObserver(self, selector: "stopTimerInBackground:", name:"stopTimerNotification", object: nil)
     NSNotificationCenter.defaultCenter().addObserver(self, selector: "startTimerInBackground:", name:"startTimerNotification", object: nil)
Run Code Online (Sandbox Code Playgroud)

Bri*_*kel 6

以下是可能的事件流程:

  1. 你呈现JobStartedViewController,它创建场景并将其添加到视图,触发didMoveToView(_:)和添加两个观察者.
  2. 您关闭视图控制器或从中删除场景SKView.在不久之后的某个时刻,没有更多强烈的引用场景,它被取消分配. 此时,通知中心仍然存在不安全的引用.
  3. 您提交另一个JobStartedViewController或以其他方式发布stopTimerNotification通知.
  4. NSNotificationCenter 尝试在解除分配的场景上执行选择器并崩溃您的应用程序.

使用时的常规做法NSNotificationCenter是在deallocObjective-C的deinit方法或Swift 的方法中删除观察者:

class GameScene: SKScene {

    // ...

    deinit {
        NSNotificationCenter.defaultCenter().removeObserver(self)
    }
}
Run Code Online (Sandbox Code Playgroud)

如果您打算多次在视图中添加和删除该场景,您还应该考虑删除您的观察者willMoveFromView(_:).