【问题标题】:NotificationCenter is not working first time when it is posted from viewcontroller to another ViewControllerNotificationCenter 在从视图控制器发布到另一个视图控制器时第一次不工作
【发布时间】:2021-05-19 20:26:20
【问题描述】:

我有 2 个 ViewController,分别称为 ViewController1 和 ViewController2。

我正在从 ViewController1 向 ViewController2 发布通知,但在第一次发布时,第一次 NotificationCenter 不起作用。

当我从 ViewController2 回到 ViewController1 并再次尝试移动 ViewController2 时,那时 NotificationCenter 正在工作,

// ViewController1.swift

import UIKit

class ViewController1: UIViewController {

override func viewDidLoad() {
    super.viewDidLoad()

}

//Move to next VC
@IBAction func nextButtonClicked(_ sender: Any) {

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

    let storyBoard = UIStoryboard(name: "Main", bundle: nil)
    let vc2 = storyBoard.instantiateViewController(withIdentifier: "ViewController2Id") as? ViewController2
    navigationController?.pushViewController(vc2!, animated: true)

  } 
}

// ViewController2.swift

import UIKit

class ViewController2: UIViewController {

override func viewDidLoad() {
    super.viewDidLoad()

    // Do any additional setup after loading the view.


}

override func viewWillAppear(_ animated: Bool) {
    //Recieve notification
    NotificationCenter.default.addObserver(self, selector: #selector(self.print1Method(notification:)), name: Notification.Name("callMethodPrint1FromVC2"), object: nil)
}

@objc func print1Method(notification: Notification) {

    print("Notification came from VC 1")
}

@IBAction func backToVC1(_ sender: Any) {

    let storyBoard = UIStoryboard(name: "Main", bundle: nil)
    let vc2 = storyBoard.instantiateViewController(withIdentifier: "ViewController1Id") as? ViewController1
    navigationController?.pushViewController(vc2!, animated: true)
}

 //Remove notification object
deinit {

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

}

实际输出

当我第一次将 ViewController1 移动到 ViewController2 时,必须调用 ViewController2 中的 print1Method 方法。

但它并没有像预期的那样工作。 我的代码中是否存在 Anu 问题或者我遗漏了什么?

【问题讨论】:

  • 按下下一个按钮时您是否尝试调用 print1Method?
  • 哈,是的。我正在尝试打印 print1Method 方法

标签: ios swift notificationcenter


【解决方案1】:

它不会调用,因为 ViewController2 没有加载,它会第二次调用,因为你在向后移动时执行的是 Push 而不是 Pop,这反过来又将 ViewController1 保留在内存中。

而是根据您的需要删除通知并从 ViewController2 Viewdidload/ViewWillappear/Viewdidappear 调用 print1Method。如果您想将一些数据从 ViewController1 传递到 ViewController2,请在 ViewController2 中保留一些公共变量并在 ViewController1 的 prepareforsegue 方法中分配值

并替换您的:

@IBAction func backToVC1(_ sender: Any) {

     let storyBoard = UIStoryboard(name: "Main", bundle: nil)
     let vc2 = storyBoard.instantiateViewController(withIdentifier: "ViewController1Id") as? ViewController1
     navigationController?.pushViewController(vc2!, animated: true)
}

@IBAction func backToVC1(_ sender: Any) {
    navigationController?.popViewController(animated: true)
}

【讨论】:

    【解决方案2】:

    您只需添加一个步骤即可做到这一点。

    我们在这里做的是在导航之前调用主视图控制器的方法 addObserver() 来注册观察者,然后,我们发布 NotificationCenter.default.post。通过这种方式,观察者首先被注册。

    First View Controller中添加这个功能在你的按钮点击

    func navigate(){
        let storyBoard = UIStoryboard(name: "travelApp", bundle: nil)
        let VC = storyBoard.instantiateViewController(identifier: "home") as! homeViewController
        VC.addObserver()
        NotificationCenter.default.post(name:Notification.Name("myNotificationName"), object: nil,  userInfo: ["hello": "world"])
        self.navigationController?.pushViewController(VC, animated: true)
    }
    

    第二个视图控制器中这样做

    class homeViewController: UIViewController {
    
    override func viewDidLoad() {
        super.viewDidLoad()
    }
    
    func addObserver(){
        print("addObserverCalled")
        NotificationCenter.default.addObserver(self, selector: #selector(onNotification(notification:)), name: Notification.Name("myNotificationName"), object: nil)
    }
    
    @objc func onNotification(notification:Notification){
        print("NotificationCenter")
        print(notification.userInfo!)
    }
    
    }
    

    【讨论】:

      【解决方案3】:

      您在视图控制器初始化之前发布通知。

      调用vc2的方法不需要贴通知。而是直接调用方法。

      在 VC1 中

      @IBAction func nextButtonClicked(_ sender: Any) {
      
           let storyBoard = UIStoryboard(name: "Main", bundle: nil)
           let vc2 = storyBoard.instantiateViewController(withIdentifier:"ViewController2Id") as ViewController2
           vc2.print1Method()
           navigationController?.pushViewController(vc2!, animated: true)
      
        } 
      }
      

      在 VC2 中

      func print1Method() {
      
           print("Method called from VC 1")
       }
      

      对于后退按钮,你做错了。只需从堆栈中弹出视图控制器

       @IBAction func backToVC1(_ sender: Any) {
      
           self.navigationController?.popViewController(animated: true)
       }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-03-11
        • 1970-01-01
        相关资源
        最近更新 更多