How do you create custom notifications in Swift 3?

You could also use a protocol for this

protocol NotificationName {
    var name: Notification.Name { get }
}

extension RawRepresentable where RawValue == String, Self: NotificationName {
    var name: Notification.Name {
        get {
            return Notification.Name(self.rawValue)
        }
    }
}

And then define your notification names as an enum anywhere you want. For example:

class MyClass {
    enum Notifications: String, NotificationName {
        case myNotification
    }
}

And use it like

NotificationCenter.default.post(name: Notifications.myNotification.name, object: nil)

This way the notification names will be decoupled from the Foundation Notification.Name. And you will only have to modify your protocol in case the implementation for Notification.Name changes.


There is a cleaner (I think) way to achieve it

extension Notification.Name {

    static let onSelectedSkin = Notification.Name("on-selected-skin")
}

And then you can use it like this

NotificationCenter.default.post(name: .onSelectedSkin, object: selectedSkin)

Notification.post is defined as:

public func post(name aName: NSNotification.Name, object anObject: AnyObject?)

In Objective-C, the notification name is a plain NSString. In Swift, it's defined as NSNotification.Name.

NSNotification.Name is defined as:

public struct Name : RawRepresentable, Equatable, Hashable, Comparable {
    public init(_ rawValue: String)
    public init(rawValue: String)
}

This is kind of weird, since I would expect it to be an Enum, and not some custom struct with seemingly no more benefit.

There is a typealias in Notification for NSNotification.Name:

public typealias Name = NSNotification.Name

The confusing part is that both Notification and NSNotification exist in Swift

So in order to define your own custom notification, do somethine like:

public class MyClass {
    static let myNotification = Notification.Name("myNotification")
}

Then to call it:

NotificationCenter.default().post(name: MyClass.myNotification, object: self)