456

How do you add an observer in Swift to the default notification center? I'm trying to port this line of code that sends a notification when the battery level changes.

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(batteryLevelChanged:) name:UIDeviceBatteryLevelDidChangeNotification object:nil];
Leo Dabus
  • 229,809
  • 59
  • 489
  • 571
Berry Blue
  • 15,330
  • 18
  • 62
  • 113
  • What are you asking specifically? How the selector works? – nschum Jun 04 '14 at 23:03
  • 1
    I didn't realize the "Selector" type is just a string in Swift. No mention of it in the docs. – Berry Blue Jun 04 '14 at 23:32
  • http://stackoverflow.com/questions/36910965/how-to-pass-data-using-notificationcentre-in-swift-3-0-and-nsnotificationcenter/36911168#36911168 – Sahil Jan 30 '17 at 06:23

17 Answers17

837

Swift 4.0 & Xcode 9.0+:

Send(Post) Notification:

NotificationCenter.default.post(name: Notification.Name("NotificationIdentifier"), object: nil)

OR

NotificationCenter.default.post(name: Notification.Name("NotificationIdentifier"), object: nil, userInfo: ["Renish":"Dadhaniya"])

Receive(Get) Notification:

NotificationCenter.default.addObserver(self, selector: #selector(self.methodOfReceivedNotification(notification:)), name: Notification.Name("NotificationIdentifier"), object: nil)

Function-Method handler for received Notification:

@objc func methodOfReceivedNotification(notification: Notification) {}

Swift 3.0 & Xcode 8.0+:

Send(Post) Notification:

NotificationCenter.default.post(name: Notification.Name("NotificationIdentifier"), object: nil)

Receive(Get) Notification:

NotificationCenter.default.addObserver(self, selector: #selector(YourClassName.methodOfReceivedNotification(notification:)), name: Notification.Name("NotificationIdentifier"), object: nil)

Method handler for received Notification:

func methodOfReceivedNotification(notification: Notification) {
  // Take Action on Notification
}

Remove Notification:

deinit {
  NotificationCenter.default.removeObserver(self, name: Notification.Name("NotificationIdentifier"), object: nil)
}

Swift 2.3 & Xcode 7:

Send(Post) Notification

NSNotificationCenter.defaultCenter().postNotificationName("NotificationIdentifier", object: nil)

Receive(Get) Notification

NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(YourClassName.methodOfReceivedNotification(_:)), name:"NotificationIdentifier", object: nil)

Method handler for received Notification

func methodOfReceivedNotification(notification: NSNotification){
  // Take Action on Notification
}


For historic Xcode versions...



Send(Post) Notification

NSNotificationCenter.defaultCenter().postNotificationName("NotificationIdentifier", object: nil)

Receive(Get) Notification

NSNotificationCenter.defaultCenter().addObserver(self, selector: "methodOfReceivedNotification:", name:"NotificationIdentifier", object: nil)

Remove Notification

NSNotificationCenter.defaultCenter().removeObserver(self, name: "NotificationIdentifier", object: nil)
NSNotificationCenter.defaultCenter().removeObserver(self) // Remove from all notifications being observed

Method handler for received Notification

func methodOfReceivedNotification(notification: NSNotification) {
  // Take Action on Notification
}

Annotate either the class or the target method with @objc

@objc private func methodOfReceivedNotification(notification: NSNotification) {
  // Take Action on Notification
}

// Or

dynamic private func methodOfReceivedNotification(notification: NSNotification) {
  // Take Action on Notification
}
Forge
  • 6,538
  • 6
  • 44
  • 64
Renish Dadhaniya
  • 10,642
  • 2
  • 31
  • 56
  • 21
    Be sure to annotate either the class or the target method with `@objc`. – Klaas Aug 24 '14 at 23:24
  • @Klaas No need to add `@objc` – goofansu Dec 29 '14 at 23:17
  • 1
    @goofansu Are you sure? I reckon that you have to add it when it's a pure Swift class. – Klaas Dec 30 '14 at 10:25
  • @goofansu &Klaas You can sent notification below three way.It's depend upon your requirement. This is a default scenario. func postNotification(notification: NSNotification) func postNotificationName(aName: String, object anObject: AnyObject?) func postNotificationName(aName: String, object anObject: AnyObject?, userInfo aUserInfo: [NSObject : AnyObject]?) – Renish Dadhaniya Dec 30 '14 at 10:50
  • @Klaas Please review my comments. – Renish Dadhaniya Dec 30 '14 at 12:07
  • The problem is that `methodOFReceivedNotication` is called dynamically. See http://stackoverflow.com/questions/26483052/nsnotificationcenter-addobserver-in-swift-while-call-a-private-method – Klaas Dec 30 '14 at 13:35
  • 10
    `methodOFReceivedNotication` must be either annotated with `dynamic` or be a member of a subclass of NSObject. – Klaas Dec 30 '14 at 13:37
  • 1
    If not, I get a runtime warning `object 0x7fd68852d710 of class 'TestNotifications.MyObject' does not implement methodSignatureForSelector: -- trouble ahead`, `Unrecognized selector -[TestNotifications.MyObject methodOFReceivedNotication:]` – Klaas Dec 30 '14 at 13:38
  • I attempted to edit your answer but needed more changes for it to go through :/. Shouldn't "methodOFReceivedNotication:" instead be "methodOFReceivedNotification:" ? – TaylorAllred Feb 25 '15 at 18:59
  • 2
    @TaylorAllred, Thank you very much for review my answer. I am really appreciate your suggestion. I have changed it. Please review it. – Renish Dadhaniya Feb 26 '15 at 04:12
  • @Klaas @ obj not necessary for me in this scenario. However as of today (3/20/2015) I still need to use it in some scenarios with core data – MobileMon Mar 20 '15 at 18:03
  • Just a note that its important to have a ":" at the end of the selector name when calling addObserver Took me a while to figure out why it was still crashing for me and this was the reason – Jase Whatson Sep 22 '15 at 01:16
  • Is there any @selecter(auto-completed method name) for swift? Typing it yourself is annoying and easy to go wrong – bluenowhere Oct 29 '15 at 02:46
  • For new selector syntax NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(Controller.methodOfReceivedNotification(_:)), name:"NotificationIdentifier", object: nil) – Steve Mar 31 '16 at 21:51
  • how to remove notification in Swift 3.0 & Xcode 8.0+? – J. Goce Jun 21 '17 at 11:11
  • @J.Goce, I have updated my answer and Add Method for the Remove Notification. Please review it and let me know if any issue.Happy Coding..:) – Renish Dadhaniya Jun 22 '17 at 04:46
  • Its not obvious what changed in between Swift 3 and 4, if you wrote out the difference that would be helpful. Thanks for the great answer! – Richard Venable Dec 06 '17 at 20:49
  • @RichardVenable, I appreciate your suggestions, My Aim is help to community and will try to provide Good code to a Lazy developer like Me :). I have added all swift version code for the Notification. Now, It's depend on developer Learn the Thing or Do copy, Paste. Looking Forward...Happy Coding...:) – Renish Dadhaniya Dec 07 '17 at 07:28
  • Nice to set up notification names like this: extension Notification.Name { static let notificationIdentifier = Notification.Name( rawValue: "notificationIdentifier") } and use like: NotificationCenter.default.addObserver(self, selector: #selector(self.methodOfReceivedNotification(notification:)), name: .notificationIdentifier, object: nil) – Giles Feb 22 '18 at 15:29
  • Apple is crazy to make such simple things so complex! – Dmitry Mar 19 '18 at 06:46
  • How to remove in Swift 4? –  Jul 31 '18 at 00:10
  • @DaniSpringer, You can remove using , Deinit: deinit { NotificationCenter.default.removeObserver(self, name: Notification.Name("NotificationIdentifier"), object: nil) } Also you can play with viewDidDisappear As per your requirements. In ARC, It will automatically remove when View release from stack. – Renish Dadhaniya Jul 31 '18 at 04:20
  • Can't I just do `NotificationCenter.default.removeObserver(self, name: .UIScreenBrightnessDidChange, object: nil)` @RenishDadhaniya (in ViewWillDisappear) –  Jul 31 '18 at 04:31
  • @DaniSpringer, YES but make sure when you will open other view It will remove. So, take care this and think about all test cases. – Renish Dadhaniya Jul 31 '18 at 04:58
  • True. Isn't viewWillDisappear called when presenting a new view modally? –  Jul 31 '18 at 05:00
  • I had added `NotificationCenter.default.addObserver...` and declared @objc in my Swift class but the @objc is never called in Xcode 13 – MrinmoyMk Jun 26 '21 at 19:38
474

It's the same as the Objective-C API, but uses Swift's syntax.

Swift 4.2 & Swift 5:

NotificationCenter.default.addObserver(
    self,
    selector: #selector(self.batteryLevelChanged),
    name: UIDevice.batteryLevelDidChangeNotification,
    object: nil)

If your observer does not inherit from an Objective-C object, you must prefix your method with @objc in order to use it as a selector.

@objc private func batteryLevelChanged(notification: NSNotification){     
    //do stuff using the userInfo property of the notification object
}

See NSNotificationCenter Class Reference, Interacting with Objective-C APIs

idrougge
  • 633
  • 5
  • 12
Connor Pearson
  • 63,902
  • 28
  • 145
  • 142
  • 15
    @BerryBlue, did the above solution work for you? I believe that you need to change "batteryLevelChanged" to "batteryLevelChanged:" if your function accepts the NSNotification as a parameter. – Olshansky Jun 05 '14 at 02:46
  • why is `UIDeviceBatteryLevelDidChangeNotification` not in quotes? It's a string type. – kmiklas Jun 18 '14 at 21:16
  • @kmiklas You can put it in quotes if you want. UIDeviceBatteryLevelDidChangeNotification is an NSString of "UIDeviceBatteryLevelDidChangeNotification". Either way you get the same result – Connor Pearson Jun 19 '14 at 01:29
  • @connor ..Until Apple decides to change the underlying string value. Use the string constant Apple gave you. – Michael Peterson Aug 15 '14 at 21:41
  • Hi, and what happened if the method batteryLevelChanged is not in the class but on another class? – SoldierCorp Aug 23 '14 at 05:02
  • @SoldierCorp Pass an instance of the other class instead of `self` – Klaas Aug 24 '14 at 23:21
  • 15
    Be sure to annotate either the class or the target method with `@objc`. – Klaas Aug 24 '14 at 23:32
  • Is there no way to avoid these string selectors? At least in Objective C when you typed @selector it would autocomplete the method names for you. Why can't they make it so you can pass functions as a parameter here? – shim Feb 11 '15 at 23:23
  • Another issue, the method must not be private func, it needs to be public for it to work – the Reverend Jun 23 '15 at 01:27
  • @shim because in `objc runtime` selectors ARE strings. Don't think in c++, the implementation of objc and c++ are totally different. – superarts.org Jul 27 '15 at 07:33
  • Right, but at least in Objective C XCode can autofill method names in @selector, helping to avoid mistakes. But in Swift, there is no such functionality. I suppose you can write let SelectorFunctionName = "functionName" above the name of a function you want to be able to use as a selector? – shim Jul 27 '15 at 22:29
  • Is that `@objc` prefix still necessary when using `#selector()` syntax? – r-dent Apr 18 '16 at 13:44
  • Marking function with @objc. Will it have some impact on performance? – Krešimir Prcela Apr 29 '16 at 11:04
  • I had added `NotificationCenter.default.addObserver...` and declared @objc in my Swift class but the @objc is never called. Do we need to post Notification as well – MrinmoyMk Jun 26 '21 at 19:05
59

A nice way of doing this is to use the addObserver(forName:object:queue:using:) method rather than the addObserver(_:selector:name:object:) method that is often used from Objective-C code. The advantage of the first variant is that you don't have to use the @objc attribute on your method:

    func batteryLevelChanged(notification: Notification) {
        // do something useful with this information
    }

    let observer = NotificationCenter.default.addObserver(
        forName: NSNotification.Name.UIDeviceBatteryLevelDidChange,
        object: nil, queue: nil,
        using: batteryLevelChanged)

and you can even just use a closure instead of a method if you want:

    let observer = NotificationCenter.default.addObserver(
        forName: NSNotification.Name.UIDeviceBatteryLevelDidChange,
        object: nil, queue: nil) { _ in print("") }

You can use the returned value to stop listening for the notification later:

    NotificationCenter.default.removeObserver(observer)

There used to be another advantage in using this method, which was that it doesn't require you to use selector strings which couldn't be statically checked by the compiler and so were fragile to breaking if the method is renamed, but Swift 2.2 and later include #selector expressions that fix that problem.

Jon Colverson
  • 2,986
  • 1
  • 24
  • 24
  • 7
    This is great! For completeness I would just like to see unregistering example too. It is quite different then the `addObserver(_:selector:name:object:) ` way of unregistering. You have to keep the object returned by `addObserverForName(_:object:queue:usingBlock:)` and pass it to `removeObserver:` – Lucas Goossen Feb 26 '16 at 13:57
  • 1
    This needs updating to include de-registration of the objected returned by `addObserverForName(_:object:queue:usingBlock:)`. – Hyperbole Mar 29 '16 at 16:55
  • 4
    This is a much better answer than connor's or Renish's (both above at time of this comment) because it gets around having to use the Obj-C #selector methods. The result is much more Swift-y and more correct, IMO. Thanks! – patr1ck Jul 16 '16 at 17:41
  • 3
    Remember, if you use this in, say, a `UIViewController` and refer to `self` in that closure, you need to use `[weak self]` or you'll have a reference cycle and the memory leak. – Rob N Oct 11 '17 at 13:39
  • 1
    All these example using selectors, seem so objective c, I was looking for a usingBlock method to see if I had to give an answer myself, also like you show the block argument didn't have to be a block but the name for a function as well. – Nathan Day Feb 09 '22 at 08:03
53
  1. Declare a notification name

    extension Notification.Name {
        static let purchaseDidFinish = Notification.Name("purchaseDidFinish")
    }
    
  2. You can add observer in two ways:

    Using Selector

    NotificationCenter.default.addObserver(self, selector: #selector(myFunction), name: .purchaseDidFinish, object: nil)
    
    @objc func myFunction(notification: Notification) {
        print(notification.object ?? "") //myObject
        print(notification.userInfo ?? "") //[AnyHashable("key"): "Value"]
    }
    

    or using block

    NotificationCenter.default.addObserver(forName: .purchaseDidFinish, object: nil, queue: nil) { [weak self] (notification) in
        guard let strongSelf = self else {
            return
        }
    
        strongSelf.myFunction(notification: notification)
    }
    
    func myFunction(notification: Notification) {
        print(notification.object ?? "") //myObject
        print(notification.userInfo ?? "") //[AnyHashable("key"): "Value"]
    }
    
  3. Post your notification

    NotificationCenter.default.post(name: .purchaseDidFinish, object: "myObject", userInfo: ["key": "Value"])
    

from iOS 9 and OS X 10.11. It is no longer necessary for an NSNotificationCenter observer to un-register itself when being deallocated. more info

For a block based implementation you need to do a weak-strong dance if you want to use self inside the block. more info

Block based observers need to be removed more info

let center = NSNotificationCenter.defaultCenter()
center.removeObserver(self.localeChangeObserver)
Tieda Wei
  • 588
  • 5
  • 14
Warif Akhand Rishi
  • 23,920
  • 8
  • 80
  • 107
  • 7
    _"from iOS 9 and OS X 10.11. It is no longer necessary for an NSNotificationCenter observer to un-register itself when being deallocated."_ This is true only for the Selector based observers. Block based observers still need to be removed. – Abhinav Nov 20 '18 at 04:04
  • You don't need to do the weak-strong dance if there is only one line of code in the block. You can just use the weak like self?.myFunction. Well that was the case with ObjC I assume it is the same in Swift. – malhal Jul 03 '20 at 08:04
  • @Abhinav how come do they have such differences? It's pretty weird. – allenlinli Jul 28 '21 at 09:11
41

Swift 3.0 in Xcode 8

Swift 3.0 has replaced many "stringly-typed" APIs with struct "wrapper types", as is the case with NotificationCenter. Notifications are now identified by a struct Notfication.Name rather than by String. See the Migrating to Swift 3 guide.

Previous usage:

// Define identifier
let notificationIdentifier: String = "NotificationIdentifier"

// Register to receive notification
NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(YourClassName.methodOfReceivedNotification(_:)), name: notificationIdentifier, object: nil)

// Post a notification
NSNotificationCenter.defaultCenter().postNotificationName(notificationIdentifier, object: nil)

New Swift 3.0 usage:

// Define identifier
let notificationName = Notification.Name("NotificationIdentifier")

// Register to receive notification
NotificationCenter.default.addObserver(self, selector: #selector(YourClassName.methodOfReceivedNotification), name: notificationName, object: nil)

// Post notification
NotificationCenter.default.post(name: notificationName, object: nil)

All of the system notification types are now defined as static constants on Notification.Name; i.e. .UIDeviceBatteryLevelDidChange, .UIApplicationDidFinishLaunching, .UITextFieldTextDidChange, etc.

You can extend Notification.Name with your own custom notifications in order to stay consistent with the system notifications:

// Definition:
extension Notification.Name {
    static let yourCustomNotificationName = Notification.Name("yourCustomNotificationName")
}

// Usage:
NotificationCenter.default.post(name: .yourCustomNotificationName, object: nil)
Jeffrey Fulton
  • 4,146
  • 1
  • 17
  • 17
11

In Swift 5

Let's say if want to Receive Data from ViewControllerB to ViewControllerA

ViewControllerA (Receiver)

import UIKit

class ViewControllerA: UIViewController  {

    override func viewDidLoad() {
        super.viewDidLoad()

        //MARK: - - - - - Code for Passing Data through Notification Observer - - - - -
        // add observer in controller(s) where you want to receive data
        NotificationCenter.default.addObserver(self, selector: #selector(self.methodOfReceivedNotification(notification:)), name: Notification.Name("NotificationIdentifier"), object: nil)
    }

    //MARK: - - - - - Method for receiving Data through Post Notificaiton - - - - -
    @objc func methodOfReceivedNotification(notification: Notification) {
        print("Value of notification : ", notification.object ?? "")
    }
}

ViewControllerB (Sender)

import UIKit

class ViewControllerB: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        //MARK: - - - - - Set data for Passing Data Post Notification - - - - -
        let objToBeSent = "Test Message from Notification"
        NotificationCenter.default.post(name: Notification.Name("NotificationIdentifier"), object: objToBeSent)
    }

}
swiftBoy
  • 35,607
  • 26
  • 136
  • 135
8

Pass Data using NSNotificationCenter

You can also pass data using NotificationCentre in swift 3.0 and NSNotificationCenter in swift 2.0.

Swift 2.0 Version

Pass info using userInfo which is a optional Dictionary of type [NSObject : AnyObject]?

let imageDataDict:[String: UIImage] = ["image": image]

// Post a notification
 NSNotificationCenter.defaultCenter().postNotificationName(notificationName, object: nil, userInfo: imageDataDict)

// Register to receive notification in your class
NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(self.showSpinningWheel(_:)), name: notificationName, object: nil)

// handle notification
func showSpinningWheel(notification: NSNotification) {
  if let image = notification.userInfo?["image"] as? UIImage {
  // do something with your image   
  }
}

Swift 3.0 Version

The userInfo now takes [AnyHashable:Any]? as an argument, which we provide as a dictionary literal in Swift

let imageDataDict:[String: UIImage] = ["image": image]

// post a notification
 NotificationCenter.default.post(name: NSNotification.Name(rawValue: "notificationName"), object: nil, userInfo: imageDataDict) 
// `default` is now a property, not a method call

// Register to receive notification in your class
NotificationCenter.default.addObserver(self, selector: #selector(self.showSpinningWheel(_:)), name: NSNotification.Name(rawValue: "notificationName"), object: nil)

// handle notification
func showSpinningWheel(_ notification: NSNotification) {

  if let image = notification.userInfo?["image"] as? UIImage {
  // do something with your image   
  }
}

Source pass data using NotificationCentre(swift 3.0) and NSNotificationCenter(swift 2.0)

Community
  • 1
  • 1
Sahil
  • 9,096
  • 3
  • 25
  • 29
5

Swift 5 Notification Observer

override func viewDidLoad() {
    super.viewDidLoad() 
    NotificationCenter.default.addObserver(self, selector: #selector(batteryLevelChanged), name: UIDevice.batteryLevelDidChangeNotification, object: nil)
}

@objc func batteryLevelChanged(notification : NSNotification){
    //do here code
}

override func viewWillDisappear(_ animated: Bool) {
    NotificationCenter.default.removeObserver(self, name: UIDevice.batteryLevelDidChangeNotification, object: nil)

}
Imran Rasheed
  • 825
  • 10
  • 25
5
  1. Create an objc function which you want to execute when notification is called.
 @objc func reloadNotification(_ notification: Notification) {
        tblview.reloadData()
    }
  1. Add the notification observer in view did load.
  NotificationCenter.default.addObserver(self, selector:#selector(reloadNotification(_:)), name: Notification.Name("reloadSideMenuDataNS"),object: nil) 
  1. post your notification where you want to call the function.
 NotificationCenter.default.post(name: Notification.Name("reloadSideMenuDataNS"), object: nil) 
  1. you can remove your notification in view did disappear with below.
 NotificationCenter.default.removeObserver(self, name: Notification.Name("reloadSideMenuDataNS"), object: nil)
Sasinderan N
  • 77
  • 1
  • 3
3

I'm able to do one of the following to successfully use a selector - without annotating anything with @objc:

NSNotificationCenter.defaultCenter().addObserver(self,
    selector:"batteryLevelChanged:" as Selector,
    name:"UIDeviceBatteryLevelDidChangeNotification",
    object:nil)    

OR

let notificationSelector: Selector = "batteryLevelChanged:"

NSNotificationCenter.defaultCenter().addObserver(self,
    selector: notificationSelector,
    name:"UIDeviceBatteryLevelDidChangeNotification",
    object:nil)    

My xcrun version shows Swift 1.2, and this works on Xcode 6.4 and Xcode 7 beta 2 (which I thought would be using Swift 2.0):

$xcrun swift --version

Apple Swift version 1.2 (swiftlang-602.0.53.1 clang-602.0.53)
leanne
  • 7,940
  • 48
  • 77
  • You don't need to annotate with `@objc` if your observer class inherits from `NSObject`. – Antonio Favata Jul 09 '15 at 13:33
  • And you shouldn't need to explicitly cast a `String` to `Selector` either. :) – Antonio Favata Jul 09 '15 at 13:33
  • @alfvata: My observer class does not inherit from NSObject. It inherits from AnyObject, Swift-style. Explicitly casting the string to Selector is allowing me to avoid doing any of the other Objective-C-related workarounds. – leanne Jul 09 '15 at 22:00
  • I'm not sure I understand how that works. I removed the `@objc` annotation from the method in my non-`NSObject` observer class, added the `as Selector` casting to the `String` selector name, and when the notification fires the app crashes. My Swift version is exactly the same as yours. – Antonio Favata Jul 10 '15 at 09:50
  • @alfavata: make sure your selector string still has a colon as the last character, as in `"selectorName:"` - otherwise it'll crash with _unrecognized selector sent to instance_. – leanne Jul 26 '15 at 16:31
  • The colon is there, and everything works fine as long as the method is annotated with `@objc`. I don't need to cast to `Selector` either. But if I remove the annotation, the notification crashes the app with the "unrecognized selector" error. – Antonio Favata Jul 27 '15 at 14:56
  • Just to add to that, my observer class doesn't inherit from anything, not even `AnyObject`. But I tried adding that as superclass and it doesn't change anything. Only if it inherits from `NSObject` or has the `@objc` annotation (either on the class definition or on the callback method) everything works as expected. – Antonio Favata Jul 27 '15 at 15:06
  • 3
    @alfavata, I don't know what to tell you. I'm now on Xcode Beta 4, and it's still working. My project is totally Swift; there are no Objective-C components. Maybe that makes a difference. Maybe there's something different in the project settings. There are any number of possibilities! I'll say: as long as the `@objc` annotation works for you, and this way doesn't, then keep annotating! – leanne Jul 27 '15 at 15:47
3

This is very simple example of custom notification observer and post

Add Notification Observer

NotificationCenter.default.addObserver(self, selector: #selector(myFunction), name: Notification.Name("CustomeNotificationName"), object: nil)

Add Selector and handle Observer call

@objc func myFunction(notification: Notification) {
    
    //Write you code
}

Post Notification(Observer) when it is required.

NotificationCenter.default.post(name: NSNotification.Name("CustomeNotificationName"), object: "Object", userInfo: ["key":"Value"])

Notes:- Make user when you leave screen you need to remove observer. e.g.

override func viewWillDisappear(_ animated: Bool) {
    super.viewWillDisappear(animated)
    NotificationCenter.default.removeObserver(self);
}
Bera Bhavin
  • 673
  • 5
  • 10
2

In swift 2.2 - XCode 7.3, we use #selector for NSNotificationCenter

 NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(rotate), name: UIDeviceOrientationDidChangeNotification, object: nil)
Deepak Thakur
  • 3,453
  • 2
  • 37
  • 65
2

We should remove notification also.

Ex.

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

}
Pankaj Jangid
  • 812
  • 9
  • 18
1

In swift 3, Xcode 8.2:- checking battery state level

//Add observer
NotificationCenter.default.addObserver(self, selector: #selector(batteryStateDidChange), name: NSNotification.Name.UIDeviceBatteryStateDidChange, object: nil)


 //Fired when battery level changes

 func batteryStateDidChange(notification: NSNotification){
        //perform manipulation here
    }
Dhruv
  • 72
  • 4
1

NSNotificationCenter add observer syntax in Swift 4.0 for iOS 11

  NotificationCenter.default.addObserver(self, selector: #selector(keyboardShow), name: NSNotification.Name.UIKeyboardWillShow, object: nil)

This is for keyboardWillShow notification name type. Other type can be selected from the available option

the Selector is of type @objc func which handle how the keyboard will show ( this is your user function )

Ashim Dahal
  • 1,097
  • 13
  • 15
  • Just to clarify for anyone reading this answer: "the Selector is of type @objc func..." means the function associated with `#selector` must be annotated with `@objc`. For example: `@objc func keyboardShow() { ... }` That threw me for a minute in Swift 4! – leanne Oct 17 '17 at 22:29
0

Swift 5 & Xcode 10.2:

NotificationCenter.default.addObserver(
            self,
            selector: #selector(batteryLevelDidChangeNotification),
            name: UIDevice.batteryLevelDidChangeNotification,
            object: nil)
A. Lebedko
  • 61
  • 9
David.Chu.ca
  • 37,408
  • 63
  • 148
  • 190
0

My favorite way of accomplishing the same thing is with Combine's .sink. This avoids needing to mark your handler with @objc.

First, create a Notification however you want. I like to use a couple extensions

extension Notification.Name {
    static var tap: Notification.Name {
        .init("tap")
    }
}

extension Notification {
    static func tap(_ point: CGPoint) -> Notification {
        Notification(name: .tap, object: point)
    }
}

UIKit / Custom Object

Then, create a register func in an object that calls NotificationCenter.default.publisher(for:):

import Combine

class TapNotifier {
    var cancellables: Set<AnyCancellable> = []

    func register() {
        NotificationCenter.default
            .publisher(for: .tap)
            .sink { [weak self] tapNotification in
                // This block is invoked any time a `.tap` notification is received.

                // Unwrap the sent object
                guard let point = tapNotification.object as? CGPoint else {
                    return
                }

                // Call your handler function
                self?.tapped(at: point)
            }
            .store(in: &cancellables)
    }

    func tapped(at point: CGPoint) {
        print("Tapped at \(point)")
    }
}

SwiftUI iOS 15<

The NotificationCenter.default publisher can also be observed on a SwiftUI view like this:

extension Notification {
    static var tap: Notification {
        Notification(name: .tap)
    }
}

struct TapsView: View {
    @State var taps: Int = 0

    var message: String {
        "Tapped button \(taps) " + (taps == 1 ? "time" : "times")
    }

    var body: some View {
        Text(message)
            .onReceive(NotificationCenter.default.publisher(for: .tap)) { tapNotification in
                // This block is invoked any time a `.tap` notification is received.
                taps += 1
            }
            .onTapGesture {
                NotificationCenter.default.post(.tap))
            }
    }
}

SwiftUI iOS 16+

struct TapsView: View {
    @State var taps: Int = 0

    var message: String {
        "Tapped button \(taps) " + (taps == 1 ? "time" : "times")
    }

    var body: some View {
        Text(message)
            .onReceive(NotificationCenter.default.publisher(for: .tap)) { tapNotification in
                // This block is invoked any time a `.tap` notification is received.

                // Unwrap the sent object
                guard let point = tapNotification.object as? CGPoint else {
                    return
                }

                taps += 1
            }
            .onTapGesture { point in
                NotificationCenter.default.post(.tap(point))
            }
    }
}
Brianna Doubt
  • 464
  • 2
  • 11