NotificationCenter is not calling the selector - ios

I've searched about this but the problem still exist for me. I found this great question but unfortunately it didn't work for me. This is the first time I'm working with NotificationCenter and the need to use this first occurs when I wanted to pass data to a viewcontroller under a tab of XLPagerTabStrip.
So here is how I am posting the Notification:
if let doc_ID = mainDoctorsArray[sender.tag].doctors_id {
NotificationCenter.default.post(name: Notification.Name("docID"), object: nil, userInfo: ["value" : doc_ID])
}
In the class I've made for observing this notification I'm calling NotificationCenter.default.addObserver(self, selector: #selector(gotDocID), name: Notification.Name("docID"), object: nil)
The selector method is:
func gotDocID(notification:NSNotification) {
let userInfo:Dictionary<String,String> = notification.userInfo as! Dictionary<String,String>
if let item = userInfo["value"] {
getDoctorDetails(docID: Int(item)!)
//print(item,self)
}
}
I've also tried adding observer as:
NotificationCenter.default.addObserver(self, selector: #selector(AvailableViewController.gotDocID(notification:)), name: Notification.Name("docID"), object: nil) but still same result.
The issue is that func gotDocID(notification:NSNotification) is not being called.
UPDATE
Class which is posting the notification is ViewController.swift and the class which has the observer is AvailableViewController.swift
Based on a comment I've changed observer to NotificationCenter.default.addObserver(self, selector: #selector(AvailableViewController.gotDocID(notific‌​ation:)), name: Notification.Name("NotificationIdentifier"), object: nil) and this error is generated.
and also by doing the follow I'm getting the same error.
Value of type 'AvailableViewController' has no member 'gotDocID'

You can use the below code to post and get data.
//Post notification
NSNotificationCenter.defaultCenter().postNotificationName("docID", object: nil, userInfo: ["value" : doc_ID])
//Get data from observer
NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(AvailableViewController.gotDocID(_:)), name: "docID", object: nil)
//Method called after notification is posted.
func gotDocID(notification: NSNotification) {
if let image = notification.userInfo?["value"] as? String {
// do something with your data
}
}

Please check :
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
NotificationCenter.default.addObserver(self, selector: #selector(self.gotDocID(notification:)), name: Notification.Name("docID"), object: nil)
}
#IBAction func saveButton(_ sender: UIButton) {
NotificationCenter.default.post(name: Notification.Name("docID"), object: nil, userInfo: ["value" : "123"])
}
#objc func gotDocID(notification:NSNotification) {
let userInfo:[String: String] = notification.userInfo as! [String: String]
if let item = userInfo["value"] {
print(item,self)
}
}
}

Add #objc to your function
#objc func gotDocID(notification:NSNotification) {
}
// Define identifier
let notificationName = Notification.Name("docID")
// Register to receive notification
NotificationCenter.default.addObserver(self, selector: #selector(AvailableViewController.gotDocID(notification:)), name: notificationName, object: nil)
// Post notification
NotificationCenter.default.post(name: notificationName, object: nil)
// Stop listening notification
NotificationCenter.default.removeObserver(self, name: notificationName, object: nil);

Why dont you try closure
Make sure your post notification occures.
Change
NotificationCenter.default.post(name: Notification.Name("docID") , object: ["value" : doc_ID])
NotificationCenter.default.addObserver(forName: Notification.Name("docID"), object: nil, queue: OperationQueue.main) { (notify) in
print(notify.object as! Dictionary<String,String>)
}

Related

Notification observer selector not called

I have this observer
override func viewDidLoad() {
super.viewDidLoad()
NotificationCenter.default.addObserver(self, selector: #selector(GetUserID(_:)), name: Notification.Name("UserID"), object: nil)
}
and this selector function
#objc func GetUserID(_ notification: Notification){
let User = notification.object as? String
self.UserID = User
}
And I keep getting nil in UserID even though I am certain that when I get the notification it is not nil which makes me believe that the selector is not being called
You can get observer value by below method
let selectedIndex:[String: Int] = ["selectedIndex": 1]
//selectedindex = 0
// post a notification
NotificationCenter.default.post(name: NSNotification.Name(rawValue: "SelectedSegment"), object: nil, userInfo: selectedIndex)
NotificationCenter.default.addObserver(self, selector: #selector(self.changeSegmentControlIndex(notification:)), name: Notification.Name("SelectedSegment"), object: nil)
#objc func changeSegmentControlIndex(notification: Notification) {
if let selectedIndex = notification.userInfo?["selectedIndex"] as? Int {
// do something with your image
print(selectedIndex)
}
}

Modal UIViewController can't receive NSNotifications

I have a modal UIViewController:
let rVC = RecoveryViewController()
rVC.modalPresentationStyle = .overFullScreen
self.present(rVC, animated: true, completion: nil)
In viewDownload of this ViewController I have a function user.checkUserData() that would send NSNotifications when the job is done.
And, of course, observers for any of these notifications:
NotificationCenter.default.addObserver(self, selector: #selector(RecoveryViewController.userVIP), name: userDataIsHere, object: nil)
But it seems that my modal ViewController is not able to receive any notifications, because nothing is happening. At the same time if I tried to add such observer to the parent UIViewController (non-modal), it'd work like a charm (actually, I checked).
My notifications are quite simple, and
let userDataIsHere = Notification.Name("userDataIsHere")
NotificationCenter.default.post(name: userDataIsHere, object: nil)
What am I doing wrong here?
Try this.
class ViewController: UIViewController {
let userDataIsHere = Notification.Name("userDataIsHere")
override func viewDidLoad() {
super.viewDidLoad()
NotificationCenter.default.addObserver(self, selector: #selector(modalPopUp), name: userDataIsHere, object: nil)
}
#objc func modalPopUp() {
let rVC = RecoveryViewController()
rVC.modalPresentationStyle = .overFullScreen
self.present(rVC, animated: true, completion: nil)
}
}
Make sure you completed below things:
1) Notification Registered before use
2) Notification identifier must be same.
Here is my code for notification:
1) Registered Notification in viewDidLoad:
let notificationName = Notification.Name("NotificationIdentifier")
NotificationCenter.default.addObserver(self, selector: #selector(yourFunctionName), name: notificationName, object: nil)
#objc func yourFunctionName(notification: NSNotification){
//do stuff
print("Called..")
}
2) Post notification when you required:
// Post notification
let notificationName = Notification.Name("NotificationIdentifier")
NotificationCenter.default.post(name: notificationName, object: nil)

NotificationCenter addObserver() issue

I'm trying to enable segue into a specific view upon opening a local notification by using NotificationCenter.addObserver(...)
My code is
override func viewDidLoad() {
super.viewDidLoad()
NotificationCenter.default.addObserver(self,
selector: #selector(LocalNotificationViewController.test), name: ???, object: nil)
}
With test method to perform the segue to ViewController with identifier NotificationView which I'm not sure what to put...
#objc func SomeNotificationAct(notification: NSNotification){
DispatchQueue.main.async() {
self.performSegue(withIdentifier: "NotificationView", sender: self)
}
}
My main question is how do I know the name of my local notification to put into the NotificationCenter.addObserver(...) method?
You will need to create extension for Notification name like,
extension Notification.Name {
static let hello1 = Notification.Name("HelloNotifcationName")
static let hello2 = Notification.Name("HelloNotifcationName2")
}
and use it like this,
NotificationCenter.default.addObserver(self, selector: #selector(setToHelloName1(notification:)), name: .hello1, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(setToHelloName2(notfication:)), name: .hello2, object: nil)
You can find further reference or tutorial,here

Change UIScrollView Offset to top from another viewController in Swift 4

I have mainViewController and inside have scrollView and I have secondViewController I want to change scrollView offset to top from secondViewController when I want to try it with NSNotificationCenter gives me ;
: unrecognized selector sent to instance 0x7ff83e024200'
How can I fix it ?
My codes under below.
mainViewController
override func viewDidLoad() {
super.viewDidLoad()
NotificationCenter.default.addObserver(self, selector: "gotop:", name: NSNotification.Name(rawValue: "gotop"), object: nil)
}
func gotop(){
scrollView.setContentOffset(CGPoint(x:0, y:0), animated: false)
}
secondViewController
#IBAction func goButton (sender : UIButton){
NotificationCenter.default.post(name: NSNotification.Name(rawValue: "gotop"), object: nil)
}
check your addObserver code, selector should have below signature
NotificationCenter.default.addObserver(self, selector: #selector(MainViewController.goTop(notification:)), name: Notification.Name("gotop"), object: nil)
Method handler for received Notification:
func goTop(notification: Notification){
scrollView.setContentOffset(CGPoint(x:0, y:0), animated: false)
}
For posting notification
NotificationCenter.default.post(name: Notification.Name("gotop"), object: nil)
Remove Notification in denit
deinit {
NotificationCenter.default.removeObserver((self, name: Notification.Name("gotop"), object: nil)
}
I have used below code in my project to add notification :
NotificationCenter.default.addObserver(self, selector: #selector(YourViewController.gotop), name: NSNotification.Name(rawValue: "gotop"), object: nil)
Try if it works in your scenario.
the definition of your "goTop" func is wrong :
instead of
func gotop(){
//do your stuff
}
try this :
func gotop(notification : NSNotification){
//do your stuff
}
let me know if this solve your problem.

How to pass data using NotificationCenter in swift 3.0 and NSNotificationCenter in swift 2.0?

I'm implementing socket.io in my swift ios app.
Currently on several panels I'm listening to the server and wait for incoming messages. I'm doing so by calling the getChatMessage function in each panel:
func getChatMessage(){
SocketIOManager.sharedInstance.getChatMessage { (messageInfo) -> Void in
dispatch_async(dispatch_get_main_queue(), { () -> Void in
//do sth depending on which panel user is
})
}
}
However I noticed it's a wrong approach and I need to change it - now I want to start listening for incoming messages only once and when any message comes - pass this message to any panel that listens to it.
So I want to pass the incoming message through the NSNotificationCenter. So far I was able to pass the information that something happened, but not pass the data itself. I was doing that by:
NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(ViewController.showSpinningWheel(_:)), name: showSpinner, object: nil)
then I had a function called:
func showSpinningWheel(notification: NSNotification) {
}
and any time I wanted to call it I was doing:
NSNotificationCenter.defaultCenter().postNotificationName(hideSpinner, object: self)
So how can I pass the object messageInfo and include it in the function that gets called?
Swift 2.0
Pass info using userInfo which is an optional Dictionary of type [NSObject : AnyObject]?
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
// For swift 4.0 and above put #objc attribute in front of function Definition
func showSpinningWheel(_ notification: NSNotification) {
if let image = notification.userInfo?["image"] as? UIImage {
// do something with your image
}
}
Swift 3.0, 4.0, 5.0 version and above
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
// For swift 4.0 and above put #objc attribute in front of function Definition
func showSpinningWheel(_ notification: NSNotification) {
if let image = notification.userInfo?["image"] as? UIImage {
// do something with your image
}
}
NOTE: Notification “names” are no longer strings, but are of type Notification.Name, hence why we are using NSNotification.Name(rawValue: "notificationName") and we can extend Notification.Name with our own custom notifications.
extension Notification.Name {
static let myNotification = Notification.Name("myNotification")
}
// and post notification like this
NotificationCenter.default.post(name: .myNotification, object: nil)
For Swift 3
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) {
print(notification.userInfo ?? "")
if let dict = notification.userInfo as NSDictionary? {
if let id = dict["image"] as? UIImage{
// do something with your image
}
}
}
For Swift 4
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
#objc func showSpinningWheel(_ notification: NSNotification) {
print(notification.userInfo ?? "")
if let dict = notification.userInfo as NSDictionary? {
if let id = dict["image"] as? UIImage{
// do something with your image
}
}
}
Hello #sahil I update your answer for swift 3
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) {
print(notification.userInfo ?? "")
if let dict = notification.userInfo as NSDictionary? {
if let id = dict["image"] as? UIImage{
// do something with your image
}
}
}
Hope it's helpful. Thanks
This is what worked for me in Swift 5
NotificationCenter.default.addObserver(self,
selector: #selector(handleMassage),
name: Notification.Name("NotificationName"),
object: nil)
The method that handles the notification:
#objc func handleMassage(notification: NSNotification) {
if let dict = notification.object as? NSDictionary {
if let myMessage = dict["myMessage"] as? String{
myLabel.text = myMessage
}
}
}
I posted it like this:
let dic = ["myMessage": "testing"]
NotificationCenter.default.post(name: Notification.Name("NotificationName"), object: dic)
Swift 5.5 with avoid #selector():
First of all, declare the name:
extension Notification.Name {
static let prettyName = Notification.Name("MyPrettyName")
}
Next is to add observer (take care with queue):
// For example transferred data should implement protocol
protocol PrettyDelegate {
func doSomethingAwesome()
}
// Here is the way how we can subscribe as observer
NotificationCenter.default.addObserver(forName: .prettyName, object: nil, queue: nil) { [weak self] notif in
guard let self = self else { return } // Because self used more than once
if let userInfo = notif.userInfo,
let delegate = userInfo["pretty"] as? PrettyDelegate {
self.delegate = delegate
}
self.makePretty() // Here we can do anything
}
Finally, we can post the notification from another object
// Here I'll illustrate how to pass optional value as userInfo
var userInfo: [AnyHashable : Any]?
if let prettyDelegate = self as? PrettyDelegate {
userInfo = ["pretty": prettyDelegate]
}
NotificationCenter.default.post(name: .prettyName, object: nil, userInfo: userInfo)
NOTE: Do NOT forget to remove the observer, when you will not need it anymore.
this is how I implement it .
let dictionary = self.convertStringToDictionary(responceString)
NotificationCenter.default.post(name: NSNotification.Name(rawValue: "SOCKET_UPDATE"), object: dictionary)
In swift 4.2 I used following code to show and hide code using NSNotification
#objc func keyboardWillShow(notification: NSNotification) {
if let keyboardSize = (notification.userInfo? [UIResponder.keyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue {
let keyboardheight = keyboardSize.height
print(keyboardheight)
}
}

Resources