Best practice for NSNotifications in Swift

So, can somebody at Apple please update the Notification Programming Topics documentation for Swift 2.2? In the meantime...


I've got a huge pile of iOS code converted from Objective-C to Swift, and so I am sitting on a lot of addObserver(..., selector: ...) calls. Like, dozens of calls. With the new warning to use #selector instead of a literal in Swift 2.2, it's got me thinking the converted code isn't sufficiently Swift-y (at least, I dont want to take the suggested fix, which makes the code super-duper unwieldy), so, I'm looking for other developers to chime in and either agree or disagree with the following.


I think the best pratice in Swift should be to not perpetuate Objective-C selectors, but instead use blocks. There's a call on NSNotificationCenter called addObserverForName(...) that takes at least one extra parameter, an NSOperationQueue, and a block.


So.


Yes? This is the right call for Swift-y code? For example, in converted code, I might have:


        NSNotificationCenter.defaultCenter().addObserver(self,
                                                         selector: "didChangePreferredContentSize:",
                                                         name: UIContentSizeCategoryDidChangeNotification,
                                                         object :nil)

And I might have a selector declared:

    func didChangePreferredContentSize(notification: NSNotification) {
        updatePreferredFontAdjustment()
    }

And in Swift 2.2, rather than add #selector(ClassName.didChangePreferredContentSize(_:)) which is IMHO garbage, I think the preferred Swift syntax should be:

        NSNotificationCenter.defaultCenter().addObserverForName(UIContentSizeCategoryDidChangeNotification, object: nil, queue: nil) { (notification) in
            self.updatePreferredFontAdjustment()
        }

Yes?

Replies

You can use blocks, but remember that you have to hold a reference to it and explicitly stop watching them if you do. I suggest instead using https://github.com/jessesquires/JSQNotificationObserverKit

FWIW, the syntax you object to:


#selector(ClassName.didChangePreferredContentSize(_:))


isn't necessary in this context. Because the instance adding the observer is the observer, you don't need the class name:


#selector(didChangePreferredContentSize(_:))


and because the method that receives the notification has a unique name [or could have a unique name, if didChangePreferredContentSize happens not to be unique, since you're the one naming it], you don't need the parameter keyword either:


#selector(didChangePreferredContentSize)


That's too ugly for you?


The awkwardness of a selector-based API is mostly historical — this API is very old. I recommend you submit a bug report requesting enhanced API that's more convenient in Swift, if you think it's currently inadequate. You won't affect any future Apple directions by expressing opinions in these forums. The only way to register your "vote" is via the bug reporting system. There is certainly a chance that in the next year or so Apple may choose to improve the least Swift-friendly Cocoa APIs, so your bug report may well influence the outcome.

Other folks have provided good answers here but I wanted to loop back to this:

So, can somebody at Apple please update the Notification Programming Topics documentation for Swift 2.2?

If you’d like to see some specific change in the documentation, you should file a bug against it. Apple tracks documentation bugs in the same way we track OS bugs.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"