【问题标题】:Call function from other ViewController从另一个 ViewController 调用函数
【发布时间】:2016-09-05 10:06:45
【问题描述】:

我有两个 ViewController,FirstViewControllerSecondViewController。两者都有自己的 Swift 文件,FirstViewController.swiftSecondViewController.swift

FirstViewController.swift 包含:

class FirstViewController: UIViewController {
    @IBAction func callFunctionInOtherClass(sender: AnyObject) {
//        Call "func showAlert" in SecondViewController when clicking the UIButton in FirstViewController
    }
}

SecondViewController.swift 包含:

class SecondViewController: UIViewController {

    @IBOutlet weak var textField: UITextField!

    func showAlert(sender: AnyObject) {
        let alert = UIAlertView(title: "Working!", message: "This function was called from FirstViewController!\nTextField says: \(textField.text!)", delegate: nil, cancelButtonTitle: "Okay")
        alert.show()
    }
}

我希望能够在点击FirstViewController 中的UIButton 时调用SecondViewController 中的func showAlert()

我已经花了很多晚上来寻找解决方案,但都没有奏效。有人知道如何实现这个目标吗?

我在这里上传了一个示例 Xcode 项目:CallFuntionInOtherClassX | filedropper.com

P.S.:当然,我可以发布一些代码并解释我得到了什么错误,但我认为这不合理,因为我真的不知道该怎么做。

【问题讨论】:

  • 为什么需要这个?这是确切的用例(即显示警报)吗?如果不是,实际用例是什么?
  • 不分配 secondviewcontroller 如何从 firstviewcontroller 调用 showAlert() 方法?
  • 使用委托或通知
  • @Losiowaty 不,这不是确切的用例。真实情况是:我有一个带有两个 ContainerViews 的 ViewController,我希望能够例如通过点击 Main/Parent-ViewController 中的按钮提交填写在 ContainerView 中的表单,因为它具有导航按钮、标题……
  • @Poles 我在编程方面不是很有经验。或许你能帮帮我?

标签: ios swift class uiviewcontroller


【解决方案1】:

您可以使用NSNotificationCentre 来完成此任务。

SecondViewController 类的viewDidLoad 方法中将自己注册为观察者以接收通知广播:-

override func viewDidLoad() {
    NotificationCenter.default.addObserver(self, selector: #selector(showAlert), name: NSNotification.Name(rawValue: "callForAlert"), object: nil)
}

FirstViewController 的按钮操作方法中,您应该通过以下方式触发通知:-

@IBAction func callFunctionInOtherClass(sender: AnyObject) {
    //Call "func showAlert" in SecondViewController when clicking the UIButton in FirstViewController
    NotificationCenter.default.post(name: NSNotification.Name(rawValue: "callForAlert"), object: nil)
}

不要忘记在 SecondViewController 的 viewDidUnload 方法中调用 removeObserver

【讨论】:

  • 非常感谢,这很有效,为我节省了几个小时。但是还有两个问题:1.你最后一句话是什么意思?这是做什么的? 2. 为什么只有你提出了这个解决方案?这是一种不常见的方式吗?因为,这似乎很容易。我想知道为什么没有其他人有这个想法。
  • Shobhakar Tiwari 还提出了实现目标动作机制的标准方法。但是您指定的案例不能由代表处理,只留下一个选项,即 NotificationCentre。并根据苹果文档:确保在观察者对象或 addObserver:selector:name:object: 中指定的任何对象被释放之前调用此方法(或 removeObserver:)。因为当在 nil 观察者上调用通知时,它可能会导致您的应用崩溃。
  • 它也有内存泄漏的影响。
  • @Eiko 我认为这个答案不值得投反对票,您可能还有其他选择,但您应该提出更好的答案,而不是投反对票,我可以看到您是 SO 社区的巨大贡献者,因为这个问题的所有者已经接受了答案。
  • 类似的问题在这里一遍又一遍地被问到 - 它应该立即作为副本关闭。我看不出为什么委托或块在这里不起作用,或者为什么将对另一个控制器的引用存储为一个简单的属性并在其上调用一个方法会失败。通知方式就像在快餐店点餐,然后等待有人喊“食物已准备好取货”——是的,它可以工作,而且没有名字,它甚至可能在第一次尝试时就到达收件人……
【解决方案2】:

编辑:这些函数已在 swift 3 中进行了如下修改:

FirstViewController 中的代码

 override function viewDidLoad(){
NotificationCenter.default.addObserver(self, selector: #selector(showAlert), name: NSNotification.Name(rawValue: "showAlert"), object: nil)
}

SecondViewController 中的代码:

@IBAction func callFunctionInOtherClass(sender: AnyObject) {
 NotificationCenter.default.post(name: NSNotification.Name(rawValue: "showAlert"), object: nil)
}

【讨论】:

    【解决方案3】:

    如果您想在转到 firstview controller 时向 second viewcontroller 显示警报视图,您可以执行类似的操作,

      self.performSegueWithIdentifier("your segue identifier", sender: self)  // or whatever way if you are not using storyboard or segue
    
        let alert = UIAlertView(title: "Working!", message: "This function was called from FirstViewController!", delegate: nil, cancelButtonTitle: "Okay")
        alert.show()
    

    如果要设置secondviewcontroller 中的任何variables,则需要实现prepareForSegue 方法。 (如果您使用的是 segue)。

    您还可以在viewDidloadsecondViewController 中显示警报视图。

    【讨论】:

    • 很遗憾,这行不通。我需要这个函数执行它SecondViewController,因为我需要@IBOutlet's 因为它是ViewController
    【解决方案4】:

    试试这个:

    SecondViewController().showAlert(self)
    

    在您的第二个视图控制器中

     if let text = textField?.text {
         dispatch_async(dispatch_get_main_queue(),{
    
          let alert = UIAlertView(title: "Working!", message: "This function was called from FirstViewController!\nTextField says: \(text)", delegate: nil, cancelButtonTitle: "Okay")
          alert.show()
    
        })
    }
    

    【讨论】:

    • 我收到fatal error: unexpectedly found nil while unwrapping an Optional value 并且它崩溃了。但是当删除警报代码并只执行print("It works!") 时,没有崩溃,我在控制台中得到了打印。
    • \(textField.text!) 似乎是问题所在。删除它时,无论有无dispatch_async,它都可以工作。有什么想法吗?
    • 首先检查它是否真的包含文本然后使用 else not
    • 我认为这不会有帮助,因为如果 textField 为空,它也会显示一个空字符串,而不是错误消息。或者,我错了吗?
    • :) 亲爱的阅读崩溃消息。在展开可选值时发现 nil
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-05-10
    • 2020-10-10
    • 2012-10-03
    • 1970-01-01
    • 2017-12-13
    • 1970-01-01
    • 2016-05-06
    相关资源
    最近更新 更多