How to create custom notifications in Swift 3?

In Objective-C, a custom notification is simply an NSString, but this is not obvious in the WWDC version for Swift 3 what exactly it should be.

+69
swift swift3 nsnotificationcenter nsnotifications nsnotification
Jun 18 '16 at 17:28
source share
10 answers

You can also use the 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 specify your notification names as enum anywhere. For example:

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

And use it like

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

Thus, notification names will be separated from Foundation Notification.Name . And you will have to change your protocol only if the implementation for Notification.Name is changed.

+17
Feb 21 '17 at 17:15
source share
— -

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

 extension Notification.Name { static let onSelectedSkin = Notification.Name("on-sekected-skin") } 

And then you can use it like this:

 NotificationCenter.default.post(name: .onSelectedSkin, object: selectedSkin) 
+231
Aug 13 '16 at 3:21
source share

Notification.post is defined as:

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

In Objective-C, the notification name is a simple NSString. In Swift, it is 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 a bit strange, as I expect it to be Enum, and not some kind of user structure that would seem to be of no more use.

In Notification for NSNotification.Name: typealias.Name:

 public typealias Name = NSNotification.Name 

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

So, to define your own notification, do the following:

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

Then call it:

 NotificationCenter.default().post(name: MyClass.myNotification, object: self) 
+31
Jun 18 '16 at 17:29
source share

A simple way:

 let name:NSNotification.Name = NSNotification.Name("notificationName") NotificationCenter.default.post(name: name, object: nil) 
+10
Feb 01 '17 at 10:16
source share

You can add a custom initializer in NSNotification.Name

 extension NSNotification.Name { enum Notifications: String { case foo, bar } init(_ value: Notifications) { self = NSNotification.Name(value.rawValue) } } 

Using:

 NotificationCenter.default.post(name: Notification.Name(.foo), object: nil) 
+9
Nov 16 '16 at 2:00
source share
 NSNotification.Name(rawValue: "myNotificationName") 
+3
Feb 27 '17 at 15:18
source share

This is just a link.

 // Add observer: NotificationCenter.default.addObserver(self, selector: #selector(notificationCallback), name: MyClass.myNotification, object: nil) // Post notification: let userInfo = ["foo": 1, "bar": "baz"] as [String: Any] NotificationCenter.default.post(name: MyClass.myNotification, object: nil, userInfo: userInfo) 
+2
09 Oct '16 at 1:34
source share

I made my own implementation by mixing things from there and there, and I find this the most convenient. Exchange for those who may be interested:

 public extension Notification { public class MyApp { public static let Something = Notification.Name("Notification.MyApp.Something") } } class ViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() NotificationCenter.default.addObserver(self, selector: #selector(self.onSomethingChange(notification:)), name: Notification.MyApp.Something, object: nil) } deinit { NotificationCenter.default.removeObserver(self) } @IBAction func btnTapped(_ sender: UIButton) { NotificationCenter.default.post(name: Notification.MyApp.Something, object: self, userInfo: [Notification.MyApp.Something:"foo"]) } func onSomethingChange(notification:NSNotification) { print("notification received") let userInfo = notification.userInfo! let key = Notification.MyApp.Something let something = userInfo[key]! as! String //Yes, this works :) print(something) } } 
+2
Apr 7 '17 at 10:03 on
source share

The advantage of using enumerations is that we get a compiler to validate the name. Reduces potential problems and simplifies refactoring.

For those who like to use enumerations instead of quoted strings for notification names, this code does the trick:

 enum MyNotification: String { case somethingHappened case somethingElseHappened case anotherNotification case oneMore } extension NotificationCenter { func add(observer: Any, selector: Selector, notification: CheckoutNotification, object: Any? = nil) { addObserver(observer, selector: selector, name: Notification.Name(notification.rawValue), object: object) } func post(notification: MyNotification, object: Any? = nil, userInfo: [AnyHashable: Any]? = nil) { post(name: NSNotification.Name(rawValue: notification.rawValue), object: object, userInfo: userInfo) } } 

Then you can use it as follows:

 NotificationCenter.default.post(.somethingHappened) 

Despite the fact that it is not related to the question, the same can be done using storyboards to avoid entering quoted lines:

 enum StoryboardSegue: String { case toHere case toThere case unwindToX } extension UIViewController { func perform(segue: StoryboardSegue) { performSegue(withIdentifier: segue.rawValue, sender: self) } } 

Then on your view controller, call it like this:

 perform(segue: .unwindToX) 
0
Jun 01 '17 at 3:31 on
source share

if you use custom notifications only for strings, there is no reason to extend any classes, but String

  extension String { var notificationName : Notification.Name{ return Notification.Name.init(self) } } 
0
Dec 6 '17 at 4:34 on
source share



All Articles