Reputation: 802
I'm am using a NSNotificationCenter in an attempt to control a timer in a SpriteKit. The code runs fine when I first enter the SKScene but when I try and re-enter the SKScene I'm getting an EXC_BAD_ACCESS error. I think that this is related to the removeObserver function. I'm not sure when to remove the observer, I tried to do it in the prepareForSegue function with no success. My viewController is as follows:
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)
}
and I add my observers to my GameScene.swift as follows:
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)
Upvotes: 2
Views: 1047
Reputation: 27550
Here's the likely flow of events:
JobStartedViewController
, it creates the scene and adds it to the view, triggering didMoveToView(_:)
and addition of two observers.SKView
. At some point shortly after, there are no more strong references to the scene and it gets deallocated. At this point there are still unsafe references to it in the notification center.JobStartedViewController
or otherwise post the stopTimerNotification
notification.NSNotificationCenter
tries performing the selector on the deallocated scene and crashes your app.The normal practice when using NSNotificationCenter
is to remove your observer in the dealloc
method for Objective-C or the deinit
method for Swift:
class GameScene: SKScene {
// ...
deinit {
NSNotificationCenter.defaultCenter().removeObserver(self)
}
}
If you are planning to add and remove that scene from your view multiple times you should also consider removing your observers in willMoveFromView(_:)
.
Upvotes: 6