NSNotification breaking in Swift when trying to pass back userInfo - ios

I'm having issues trying to pass back userInfo via postNotification in Swift. What's strange is the code only breaks when I try to use userInfo -- if I post a notification with no data to a selector with no parameters, everything works. But when I try to pass back userInfo, I get a "unrecognized selector sent to instance" error. So something's wrong with my selector signature in my ViewController, but I can't figure out what.
Here is the code that breaks:
In my table view
let data = ["selection": selectedOption]
dismissViewControllerAnimated(true, completion: {NSNotificationCenter.defaultCenter().postNotificationName(wordsetPickedNotification, object: self, userInfo: data)})
In my view controller:
NSNotificationCenter.defaultCenter().addObserver(self, selector: "wordsetPicked", name: wordsetPickedNotification, object: nil)
...
func wordsetPicked(n:NSNotification) {
//do stuff
}

Change selector: "wordsetPicked" to selector: "wordsetPicked:".

Related

Notification Center Posting Notification with User-Info

For my code base, I have 3 functions and 3 dispatch groups (dg)
so when the 1st function is done, dg1's notify method is called and it calls func 2, and once that is done, dg2's notify method is called and func 3 is called once that is finished dg3's notify is called, I have my data and I use it for further processing.
All the above logic is in another file
I want to pass the data is of func 3, available in dg3's notify-execute method to my vc. I employed the notification center for this method. Using the following:
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
}
}
However I never get the notification. How do I resolve this problem. I want to pass the data from the dispatch group elsewhere -in this case my VC.

How to readd a notification observer

So I have about four notification observers added in a particular view controller, but I want to remove one in particular if a condition is met and then add it back for a different condition. I was able to remove the particular observer but I have had trouble adding it back. the other ones work except the one a removed and added back and I know it's working cos when the VC loads and all the notification observers are added but then it stops working after adding it back. here's my code:
// registered the observer in ViewDIdAppear and this registers my bluetooth device and whenever i tap on the bluetooth device button this function gets called
NotificationCenter.default.addObserver(
self, selector: #selector(Myclass.deviceTapped), name: Notification.Name("bluetoothRecievedNoticicationName"), object: nil)
// i removed the observer here
if condition == false {
NotificationCenter.default.removeObserver(self, name: Notification.Name("bluetoothRecievedNoticicationName"), object: nil)
}
// and then use this to add it back again
NotificationCenter.default.addObserver(
self, selector: #selector(Myclass.deviceTapped), name: Notification.Name("bluetoothRecievedNoticicationName"), object: nil)
// and after adding this ^ back the deviceTapped function doesn't get called anymore
The thing to do in these situations is prove to yourself that this does normally work. That way, you can track down what you are doing that prevents it from working.
For example, perhaps self is going out of existence before any notifications have a chance to arrive...? Perhaps some other code, that you have not shown, is unregistering you again...? I've certainly experienced confusions like that! And they can be very hard to debug.
But whatever the explanation, you need first to assure yourself that unregistering for a notification and then re-registering for it is not a problem.
Here's a test app. It has three buttons: Register, Unregister, and Notify. Here's the code:
let notif : Notification.Name = .init("howdy")
#objc func gotNotified() {
print("got notified")
}
#IBAction func doRegister(_ sender: Any) {
NotificationCenter.default.addObserver(self, selector: #selector(gotNotified), name: notif, object: nil)
}
#IBAction func doUnregister(_ sender: Any) {
NotificationCenter.default.removeObserver(self, name: notif, object: nil)
}
#IBAction func doNotify(_ sender: Any) {
NotificationCenter.default.post(name: notif, object: nil)
}
So configure that with the buttons hooked up, and then:
Tap Register.
Tap Notify.
Tap Unregister.
Tap Notify.
Tap Register.
Tap Notify.
You will see that on 2 and 6, but not 4, we print to the console to prove we were notified — just as you would expect.

NotificationCenter throw error when adding observer with selector function

In the server side I use socket.io library to send some JS object data type through, upon users typing in their devices:
var typingUsers = {};
clientSocket.on("startType", function(clientNickname){
typingUsers[clientNickname] = 1;
io.emit("userTypingUpdate", typingUsers);
});
when the app receives data, it will post notification:
private func listenForOtherMessages() {
socket.on("userTypingUpdate") { (dataArray, socketAck) -> Void in
NotificationCenter.default.post(name:NSNotification.Name(rawValue: "userTypingNotification"), object: dataArray[0] as! [String: AnyObject])
}
}
And then the notification is added to a view controller as an observer:
NotificationCenter.default.addObserver(self, selector: Selector(("handleDisconnectedUserUpdateNotification:")), name: NSNotification.Name(rawValue: "userWasDisconnectedNotification"), object: nil)
This implementation always throw an error "unrecognised selector send to ..."
But the following implementation without a selector works ok:
NotificationCenter.default.addObserver(forName:NSNotification.Name(rawValue: "userTypingNotification"), object: nil, queue: nil){ object in
print(object)
}
It seems like I cannot add an selector to the observer, I think the problems might lie in the object data type, but I cannot really figure out why..
found the answer:
NotificationCenter.default.addObserver(self, selector: #selector(self.userTypingNotification), name: NSNotification.Name(rawValue: "userWasDisconnectedNotification"), object: nil)
older post

removeObserver for Notification Swift3

I have a strange issue. I register and unregister my Notification like so:
func doRegisterNotificationListener() {
NotificationCenter.default.addObserver(forName: Notification.Name(rawValue: "RateAlertRated"), object: nil, queue: nil, using: rateDidRate)
}
func doUnregisterNotificationListener() {
NotificationCenter.default.removeObserver(self, name: Notification.Name(rawValue: "RateAlertRated"), object: nil)
}
func rateDidRate(notification: Notification) {
let rating = notification.userInfo?["score"] as? Int
let message = notification.userInfo?["message"] as? String
let response = Response(rating: rating, message: message)
output.presentRated(response)
}
This view controller is in a UITabBarController. doRegisterNotificationListener is called in viewDidAppear and doUnregisterNotificationListener is called in viewDidDisappear. When I switch between tabs the register and unregister methods are being called correctly (I tested using a print statement). However if I fire a notification it will still be received even though doUnregisterNotificationListener was called last. Any ideas what I might be doing wrong here?
Quick note:
Also tried:
NotificationCenter.default.removeObserver(self)
This also doesn't work.
I have tested your code and once i register observer with this type it is not called when you doUnregister it. please try this.
NotificationCenter.default.addObserver(self, selector: #selector(rateDidRate(notification:)), name: Notification.Name(rawValue: "RateAlertRated"), object: nil)
If you are working with addObserver(forName:object:queue:using:) you should remove it in this way:
Create:
let center = NSNotificationCenter.defaultCenter()
let mainQueue = NSOperationQueue.mainQueue()
self.localeChangeObserver = center.addObserverForName(NSCurrentLocaleDidChangeNotification, object: nil, queue: mainQueue) { (note) in
print("The user's locale changed to: \(NSLocale.currentLocale().localeIdentifier)")
}
Remove:
center.removeObserver(self.localeChangeObserver)
This approach is taken from the documentation.

can we update ViewController from didRegisterForRemoteNotificationsWithDeviceToken by checking isRegisteredForLocalNotifications

Hi i am new in iOS application development. I am using Swift 3.0 code.
In my application I'm fetching the device token and I'm passing to my server. to pass token value from Appdelegate to UIViewController i am using UserDefaults.standard. and it's working fine. During first application load i am showing system's push notification prompt. If user click OK (allow) or Don't allow. application check it using following code.
//Checking Notification State
let isRegisteredForLocalNotifications = UIApplication.shared.currentUserNotificationSettings?.types.contains(UIUserNotificationType.alert) ?? false
if isRegisteredForLocalNotifications{
print("Notification allow")
}else{
print("Notification Don't allow")
}
Note: The above code is working fine in didRegisterForRemoteNotificationsWithDeviceToken.
I am having following issue with above code.
1) if i am using same code in ViewController its working but my application not waiting for system's push notification prompt result. i am getting results in AppDelegate.
So how to reload ViewController from didRegisterForRemoteNotificationsWithDeviceToken? is there any way to do that.
2) can i pause viewController until user response to system's push notification prompt. But i am not sure above code will work in ViewController or not.
Please advise.
Thanks for help.
For first part of your problem, you can create an Observer:
NotificationCenter.default.addObserver(self, selector: #selector(YourClassName.methodOfReceivedNotification(notification:)), name: Notification.Name("NotificationIdentifier"), object: nil)
the function that handle it will be like this:
func methodOfReceivedNotification(notification: Notification){
//Take Action on Notification
}
and then you can call it as follows:
NotificationCenter.default.post(name: Notification.Name("NotificationIdentifier"), object: nil)
you can call the above code whenever you want to update your viewController
You can update view controller from didRegisterForRemoteNotificationsWithDeviceToken? by post notification.
let notificationIdentifier: String = "NotificationIdentifier"
//write this to didRegisterForRemoteNotificationsWithDeviceToken
// Post notification
NotificationCenter.default.post(name: notificationName, object: nil)
//write this to your View Controller
let notificationIdentifier: String = "NotificationIdentifier"
// Register to receive notification
NotificationCenter.default.addObserver(self, selector:#selector(YourClassName.methodOfReceivedNotification), name: notificationName, object: nil)
// Stop listening notification
NotificationCenter.default.removeObserver(self, name: notificationName, object: nil);
func methodOfReceivedNotification(notification: Notification) {
}

Resources