Observer class not receiving notifications - ios

I have a class that handles the notification. I can add the observer to NotificationCenter but the handles method never executes. If I move the same method into the class that adds the observer it works fine.
I've tried putting it in the class and it works fine just not from a different object. This is on Swift 4.2. I have also printed out all the observers via: print("Exp - NC - \(NotificationCenter.default.debugDescription)")
and can see the observer was added for the .purchase name.
// Works
SomeClass.swift
// Works assuming notify handler is in this class
NotificationCenter.default.addObserver(self, selector: #selector(notify(_:)), name: .purchase, object: nil)
// Does not work
MyObserver.swift
import Foundation
#objc
public class MyObserver: NSObject {
#objc
public override init() {
print("Observer here creating a new instance")
}
#objc public func onNotification(_ notification: Notification) {
print("Observer 1 here notifying event")
}
}
SomeClass.swift
let myObserver = MyObserver()
NotificationCenter.default.addObserver(myObserver, selector:
#selector(myObserver.onNotification(_:)), name: .purchase, object:
nil)
Note: .purchase is an extension of Notification.Name
I would expect it to notify via the myObserver class as well. Seems like it only works with self. The only difference is the observer is a custom object instead of self

Related

How to register Notification Center in class iOS

I am new to ios programming, I wanted to register notification center in the class, not in the view controller, I want to send some action from one view controller this custom class receives that action and it performs some view controller navigation.I wanted to have custom notification center in ios.
code:
NotificationCenter.default.post(name: Notification.Name(rawValue: "key"), object: nil)
class MainReceiver: NotificationCenter
{
override func post(name aName: NSNotification.Name, object anObject: Any?)
{
print("coming here")
}
}
Here you have snipped code:
class MainReceiver {
init() {
NotificationCenter.default.addObserver(self, selector: #selector(handleMethod(_:)), name: NSNotification.Name(rawValue: "Notification_Name"), object: nil)
}
deinit {
NotificationCenter.default.removeObserver(self)
}
#objc func handleMethod(_ notification: Notification) {
// handle
}
}
From Apple's NSNotificationCenter documentation:
Each running Cocoa program has a default notification center. You typically don’t create your own.
I'm not sure why you think you want to create your own notification center, but trust me, you don't.
However, you can easily subscribe an object (an instance of a custom class, like you say you want to use) to notifications:
// let object = Whatever()
NotificationCenter.default.addObserver(object, selector: #selector(didReceive(notification:)), name: NSNotification.Name(rawValue: "key"), object: nil)
// object's didReceive(notification:) function will now be called when a notification with the specified name is posted. This can be posted from anywhere.
A while back, the function had to be decorated with the #objc attribute. I'm not sure if that's still the case, but if so, you'd use #objc func didReceive(notification: Notification) as your declaration in the receiving class.
If I understand your question correctly I think what you are looking for is the blocked based variant for the NotificationCenter.
You can find it in the official docs.
Example code from the docs:
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)")

How to use selector function from different class in iOS Swift, mainly for NotificationCenter

I am using Tab Bar Controller in an iOS app and I am using reachability for checking the network availability and for achieving it I am using Notifications.
The basic syntax of a notification in Swift 3 is as follows -
NotificationCenter.default.addObserver(observer: Any, selector: Selector, name: NSNotification.Name?, object: Any)
and things happen generally this way -
NotificationCenter.default.addObserver(observer: self, selector: #selector(ViewControllerName.functionName), name: NameOfTheNotification, object: nil)
What I want to do is -
I want to use a static function present in different class for selector i.e.., when this notification is generated I want to call the static function which is present in the different class.
let's say the class name is "Functions" and the name of function is "myFunction()"
in simple words what I want to do is whenever the notification is there I want to call myFunction() function from class Functions.
What I had tried
I had tried doing this but it doesn't help -
NotificationCenter.default.addObserver(observer: Functions(), selector: #selector(Functions.myFunction), name: NameOfTheNotification, object: nil)
There occurs an error and that error is as follows -
I had attached the Xcode snapshot below.
The easiest fix is to add #objc to reachabilityStatusChanged.
// ↓
#objc func reachabilityStatusChanged(notification: Notification) {
...
}
But NotificationCenter doesn't really require your class to support Objective-C. You could use the block variant of the method:
NotificationCenter.default.addObserver(forName: Notification.Name("ReachStatusChanged"), object: nil, queue: nil) { notification in
// do whatever Swift code with `notification` here.
// no need to add #objc anywhere.
reachabilityStatusChanged(notification)
}
The main problem you're experimenting here is the interoperability with obj-C.
Make sure you expose the function `reachabilityStatusChanged' to obj-C with the #objc annotation.
#objc func reachabilityStatusChanged
Also, make sure the class Functions is visible to obj-c. (Inheriting it from NSObject)
An illustration of why you have to retain Functions()
class Foo {
#objc func test() {
print("Hello")
}
}
var foo: Foo? = Foo()
let nc = NotificationCenter.default
nc.addObserver(foo!,
selector: #selector(Foo.test),
name: NSNotification.Name(rawValue: "Barrr"),
object: nil)
nc.post(name: NSNotification.Name(rawValue: "Barrr"), object: nil)
nc.post(name: NSNotification.Name(rawValue: "Barrr"), object: nil)
foo = nil
nc.post(name: NSNotification.Name(rawValue: "Barrr"), object: nil)
This will print Hello twice instead of three times because foo class was deallocated before the third call.

NotificationCenter not receiving posts

I have a class that accepts accelerometer data and posts it in a notification like so:
func notify(accel: accelPoint){
NotificationCenter.default.post(name: Notification.Name("newRawData"), object: nil)
}
And two objects set up to observe this, the first being a viewController:
override func viewDidLoad() {
super.viewDidLoad()
NotificationCenter.default.addObserver(self, selector: #selector(FirstViewController.newRawData), name: Notification.Name("newRawData"), object: nil)
Which calls the function:
func newRawData(notification: NSNotification){ ...
This works just fine.
The other observer is in a regular Swift class, instantiated in the app delegate. (I have tried doing this before and after creating the notifying class):
init(){
NotificationCenter.default.addObserver(self, selector: #selector(FilterManager.newRawData), name: Notification.Name("newRawData"), object: nil)
}
Which should call the function below but for some reason it does not.
#objc func newRawData(){
print("WHYYY")
}
The name this class is correct, and I have seen the the observer is being registered and the notifications are being posted so why isn't this class being notified like the other?
Also, why do I have to expose the newRawData function in the second class to objective-C but not the newRawData in the viewController class?
did you referenced FilterManager class in your AppDelegate? if not add this code in you AppDelegate class. also you can make FilterManger singleton to solve this problem.
var filterManger = FilterManager()

UIApplicationSignificantTimeChange notification is not triggered

I want to use the UIApplicationSignificantTimeChange to check when the day has changed and I encapsulated in my own class so I can easy use it in more view controllers:
public final class DayChangedObserver {
private var token: NSObjectProtocol!
public init?(handler: #escaping () -> ()) {
token = NotificationCenter.default.addObserver(forName: NSNotification.Name.UIApplicationSignificantTimeChange, object: self, queue: nil) { _ in
handler()
}
}
deinit {
NotificationCenter.default.removeObserver(token)
}
}
And I call this code from my view controller:
override func viewDidLoad() {
super.viewDidLoad()
_ = DayChangedObserver() {
print("Day has changed")
}
}
I am testing this on my iPhone and I manually change the time. But it seems that it doesn't work using my class.
Is it something wrong with my implementation ? Because it was working when I was using this event in the past (without my own class implementation).
EDIT1:
I seems that deinit is called immediately after, so I am using an instance variable to keep a strong reference and now it's not deinit anymore, but still doesn't work.
object: self change to object: nil,try it.

How to call a function from a different view controller with different classes

When you press on the screen im trying to get a function that Is in a different view Controller to be called usaully i would just do the
viewControllerFuncIsIn().NameOfFunc()
but because the view controller class that has the function im trying to call is a SCNView. it gives me this error with ns coder because in currently in a Skscene
the function im trying to call is in a class called Extra1 right below the viewdidload(not in it).
Update for comment below:
Extra1(coder:NSCoder())!.see()
Small example for you:
Use delegate when connection is one to one.
Delegate:
Create protocol:
protocol TestViewControllerDelegate {
func finishTask(sender: TestViewController)
}
Create reference for delegation. It should be weak it is important.
weak var delegate:TestViewControllerDelegate?
Exited you're class.
extension MainViewController: TestViewControllerDelegate {
func finishTask(sender: TestViewController) {
}
}
Call delegate:
delegate?. finishTask(self)
Use notification when connection is one to many.
Notification:
Add observer for notification.
NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(ClassName.test), name:"NotificationIdentifier", object: nil)
Post notification.
NSNotificationCenter.defaultCenter().postNotificationName("NotificationIdentifier", object: nil)
I fond the answer to my question
func mySelector(elem: AnyObject) {
Extra1().see()
}
NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(self.mySelector), name: "see", object: nil)
NSNotificationCenter.defaultCenter().postNotificationName("see", object: self)

Resources