1

I have a UILabel extension and what to add and remove custom NSNotification in there.

public extension UILabel {

    @IBInspectable var localizedText: String? {

        get { return text }
        set {
            NotificationCenter.default.removeObserver(self, name: NSNotification.Name(rawValue: LCLLanguageChangeNotification), object: nil)
            NotificationCenter.default.addObserver(forName: NSNotification.Name(rawValue: LCLLanguageChangeNotification), object: nil, queue: .main) { [weak self] (notification) in
                guard let strongSelf = self else {
                    NotificationCenter.default.removeObserver(self, name: NSNotification.Name(rawValue: LCLLanguageChangeNotification), object: nil)
                    return
                }
                strongSelf.text = strongSelf.localizedText?.localized()
            }
            text = newValue?.localized()
        }
    }
}

Problem that I see in this solution is that when

self

is nil, its impossible to remove observer, so this notification will fire even when UILabel was removed from UIWindow stack.

Is there any workaround for this?

zisoft
  • 22,770
  • 10
  • 62
  • 73
Narek Simonyan
  • 572
  • 1
  • 7
  • 18

2 Answers2

2

From the Apple Docs NotificationCenter.removeObserver

If your app targets iOS 9.0 and later or macOS 10.11 and later, you don't need to unregister an observer in its dealloc method.

So there is no need to take care of the parent object holding the observer anymore.

zisoft
  • 22,770
  • 10
  • 62
  • 73
  • Ok Thanks, so that means that this code is valid and will work without any leaks or issues? – Narek Simonyan Sep 25 '18 at 11:41
  • Just remove the `removeObserver` calls from your code, they are not neccessary anymore. – zisoft Sep 25 '18 at 11:47
  • @zisoft That is not entirely true. Only those who are making an selector reference are automatically removed. Those who have an open block as the one he have, wont unregister automatically. https://oleb.net/blog/2018/01/notificationcenter-removeobserver/ – Vollan Sep 26 '18 at 06:31
2

According to Apple Docs as zizoft mentioned:

If your app targets iOS 9.0 and later or macOS 10.11 and later, you don't need to unregister an observer in its dealloc method.

This is quite shady, as users have experienced that it's not working on all cases. This is one example

What this blogger figured out is that it is only automatically removed if you have an selector refeference. Hence, you can't have an open block as you have it. Instead i would create it like this:

extension UILabel {

        func addStuff() {
            NotificationCenter.default.addObserver(self, selector: #selector(doStuff), name: NSNotification.Name(rawValue: LCLLanguageChangeNotification), object: nil)
        }

        @objc func doStuff() {

        }
    }

Of topic is that i would use a better name handler than you have, take a look Here and it will be alot cleaner:

Vollan
  • 1,887
  • 11
  • 26