Home > database >  why NotificationCenter.observer is not listening to notifications
why NotificationCenter.observer is not listening to notifications

Time:09-16

Hai guys I am new to iOS development and still learning

I have a three View controllers ,viewController, SViewController, TViewController

in SviewController I have notification sender.post method on clicking a button

in viewController, TViewController viewdidload() methods I have .addobserver() methods

when I click a button on SViewController and post the notification

View Controller's selector is executed and not the TviewController

I have loaded the TviewController in FirstVC i.e ViewController viewdidload() method only

since segue performs again a viewdidload() from SviewController to TviewController with another button ,I tried to allocate a completion handler string to global variable so that it value remains same and print it(changed value) when view is loaded again, then I came to know that the completion handler is not at all executing here is the code

ViewController

import UIKit

extension Notification.Name{
    static var fnote = Notification.Name("fnote")
}

class ViewController: UIViewController {
@IBOutlet weak var label: UILabel!

override func viewDidLoad() {
    super.viewDidLoad()
 
    NotificationCenter.default.addObserver(self, selector: #selector(fhandle(notification:)), name: .fnote, object: nil)
    
    let storyboad = UIStoryboard(name: "Main", bundle: nil)
    let tvc = storyboad.instantiateViewController(identifier: "1") as! TViewController
    
    let _ = tvc.view
    print(tvc.isViewLoaded)
    
    print("journey")
}

@objc func fhandle(notification:Notification){
    label.text = "Haii welcome to the hyderabad"
}


}

SViewController

import UIKit
var temp:String = "HHH"

class SViewController: UIViewController {

 
 
    @IBAction func click(_ sender: Any) {
        
        NotificationCenter.default.post(name: .fnote, object: nil)
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()

        // Do any additional setup after loading the view.
    }
}

TviewController

import UIKit



class TViewController: UIViewController {

    @IBOutlet weak var label2: UILabel!
    
    override func viewDidLoad() {
        super.viewDidLoad()

        NotificationCenter.default.addObserver(self, selector: #selector(handler(notification:)) , name: .fnote, object: nil)
       
        print(temp)
        print("happy")
    }

   @objc func handler(notification:Notification)
    {
        print("jackson")
        label2.text = "Hurray"
        temp = label2.text ?? "Nothing"
    }
}

Can Some one please help me with this

CodePudding user response:

let storyboad = UIStoryboard(name: "Main", bundle: nil)
let tvc = storyboad.instantiateViewController(identifier: "1") as! TViewController
let _ = tvc.view
print(tvc.isViewLoaded)

This is not the way to test the notification. Push your "TViewController" controller from the "ViewController" controller. Then post notification from your target controller.

CodePudding user response:

You haven't shown or explained where / when / how you're going to display the view from TViewController, but to explain the first thing you're doing wrong...

In this code:

override func viewDidLoad() {
    super.viewDidLoad()
 
    NotificationCenter.default.addObserver(self, selector: #selector(fhandle(notification:)), name: .fnote, object: nil)
    
    let storyboad = UIStoryboard(name: "Main", bundle: nil)
    let tvc = storyboad.instantiateViewController(identifier: "1") as! TViewController
    
    let _ = tvc.view
    print(tvc.isViewLoaded)
    
    print("journey")
}

as soon as viewDidLoad() finishes (that is, immediately after the print("journey") line), your tvc instance of TViewController is destroyed. That is, it's dumped from memory and no code inside it can execute, because it no longer exists.

That's called "going out of scope."

So, when you try to post a notification from SViewController, there is no TViewController in existence so its code is not running to "observe" the notification.

Here is a very simple example of multiple view controllers observing a notification:

enter image description here

When you push from ViewController to TViewController, you get a new instance of TViewController and the original instance of ViewController still exists.

When you push from TViewController to SViewController, you get a new instance of SViewController and both ViewController and TViewController still exist.

When you tap the "Post" button, ViewController and TViewController will each execute the func you assigned to observe the notification.

When you then go Back to TViewController, you'll see its label text has changed, and when you go back to ViewController you'll see its label text has also changed.

Note that if you then push to TViewController again, you get a new instance and its label will be back at its original text.

extension Notification.Name{
    static var fnote = Notification.Name("fnote")
}

class ViewController: UIViewController {
    
    @IBOutlet weak var label: UILabel!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        NotificationCenter.default.addObserver(self, selector: #selector(fhandle(notification:)), name: .fnote, object: nil)
        print("journey")
    }
    
    @objc func fhandle(notification:Notification) {
        print("Got it!")
        label.text = "Haii welcome to the hyderabad"
    }
    
}

class TViewController: UIViewController {
    
    @IBOutlet weak var label2: UILabel!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        NotificationCenter.default.addObserver(self, selector: #selector(handler(notification:)), name: .fnote, object: nil)
        print("happy")
    }
    
    @objc func handler(notification:Notification) {
        print("jackson")
        label2.text = "Hurray"
    }

}

class SViewController: UIViewController {

    @IBOutlet var infoLabel: UILabel!
    
    @IBAction func click(_ sender: Any) {
        NotificationCenter.default.post(name: .fnote, object: nil)
        infoLabel.text = "Notification Posted"
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
    }
}
  • Related