Search code examples
iosswiftexc-bad-accessnsnotificationcenter

NotificationCenter: BAD_ACCESS when Notification postet


I have an app with 3 viewcontrollers that are pushed on a navigation controller stack.

(A) -> (B) -> (C)

(A) registers for notifications in viewWillAppear:

NotificationCenter.default.addObserver(self, selector: #selector(reload), name: NSNotification.Name(rawValue: "DATA_CHANGED"), object: nil)

and (A) deregisters in viewWillDisappear:

NotificationCenter.default.removeObserver(self, name: NSNotification.Name(rawValue: "DATA_CHANGED"), object: nil)

Additionally (A) deregisters in deinit() but this is never called.

Now (B) is pushed on stack and registers /deregisters for the same event like (A).

Now (C) is pushed on stack that triggers a computation and pops back to (B). Some time later while (B) is presented the computation is finished and a Notification is fired:

NotificationCenter.default.post(name: NSNotification.Name(rawValue: "DATA_CHANGED"), object: nil)

But this results in an

Thread 1: EXC_BAD_ACCESS

I'm sure that the notification is the problem because i misspelled the notification name and then no crash occurred. Also (A) and (B) are still not deallocated as the are living on the stack. I could not find any Zombie in Profiler.

Any idea what might be the problem?

I'm using XCode 9beta6 and Swift 4.


Solution

  • So I just spent about 4 hours fixing this in my own code. Here is what my problem was:

    The function I specified in my selector had an optional parameter with a default value of nil. My selector then looked just like yours - no parameter list. However, when I was firing a notification, I was getting EXC_BAD_ACCESS.

    I was trying to call a parent's function with my selector in relation to the child class I was registering the notification on. I had to make a helper function on the child class and call the parent's function.

    If you have an optional parameter in reload and/or reload is a function in a parent class, try making a helper function which calls reload and make your selector point to that.