【问题标题】:Using Swift, how do I call a function coded in one view controller from a button in another view controller?使用 Swift,我如何从另一个视图控制器中的按钮调用在一个视图控制器中编码的函数?
【发布时间】:2016-02-05 10:08:20
【问题描述】:

我通过参加一些有关 Swift 编程语言的在线课程开始学习编程。我正在试验一个 Xcode 项目,其中我的主情节提要中有两个视图控制器。

在项目中,我有一个按钮将我从视图控制器 1 带到视图控制器 2。视图控制器 2 有三个按钮:

  • 通过邮件应用程序触发一封新电子邮件
  • 关闭屏幕并将用户返回到第一个视图控制器屏幕
  • 第三个应该调用一个函数(该代码位于第一个视图控制器的 ViewController.swift 中)。

有问题的函数其实很简单:

func ResetGame()
{
    PlaySoundButton()
    score = 0
    totalquestionsasked = 0

}

我已经记不清我试图让它工作的所有方式,但最初我认为它只是一个简单的按钮,在第二个视图中具有以下代码 sn-ps 之一:

@IBAction func buttonResetGame(sender: UIButton) {

    ResetGame()
}

或者

 @IBAction func buttonResetGame(sender: AnyObject) {

        ResetGame()
    }

但这当然会导致 Use of unresolved identifier 'ResetGame' 错误。

我还尝试按照以下示例直接在按钮代码中对函数进行编码:

@IBAction func buttonResetGame(sender: UIButton) {

    PlaySoundButton()
    score = 0
    totalquestionsasked = 0

}

当然,那也没用。

我对此进行了研究,看来这在 Objective C 和其他编程语言中是可能的,但我似乎无法找到使用 Swift 的示例。这是否意味着这是不可能的,或者只是它没有完成?

总结:

  • 这可能吗?
  • 如果是,怎么做?
  • 如果不推荐,为什么不呢?
  • 最后,推荐的跨视图控制器使用函数的方法是什么?

【问题讨论】:

  • 你能发布一些代码吗?特别是有问题的功能。然后我们可以就最佳解决方案提出建议。
  • @RMenke 不用担心,只是编辑了问题以包含代码。可以看到,函数很简单。
  • 谷歌单例和委托。这个问题之前已经被问过很多次了,在swift中有很好的答案。
  • @RMenke 好的,太好了!谢谢!
  • @Lubos 在我的一门在线课程中,我刚刚发现了 UIViews。如果我在主视图控制器中使用 UIView 来执行我当前在第二个视图控制器中所做的事情,这是否意味着位于 UIView 中的按钮、标签等的所有编码都将属于同一个视图控制器?如果是这样,我是否能够从 UIView 中的按钮调用该函数,而不是尝试从第二个视图控制器执行它? (我的第二个视图控制器旨在提供更多信息/帮助、电子邮件反馈和重置分数的能力)。这是一个实用的解决方案吗?

标签: ios swift


【解决方案1】:

一般来说,这是可能的,但不推荐,因为视图控制器用于显示视图,而不是用于在不同视图控制器之间共享功能。

您应该通过创建一个单独的类来实现这一点,以便从两个视图控制器中引用,您将在其中定义此函数,该函数包含通用功能。

已编辑: 如果您不想从 2 个视图控制器共享通用功能,而只需要从另一个控制器调用一些代码,则可以使用委托模式,如

class FirstController: UIViewController, YourProtocol {

     override func prepareForSegue(segue: UIStoryboardSegue?, sender: AnyObject?) {

         if segue?.identifier == "yourSegueName" {
             let viewController = segue!.destinationViewController as! SecondController
             viewController.controller = self
         }
     }

     func someFunction() {

     }
}

class SecondController: UIViewController {

     var controller: YourProtocol?   // reference to the delegate alias First Controller

         override func viewDidLoad() {
              super.viewDidLoad()
              controller.someFunction()   // call function from the delegate alias first controller
    }

}

protocol YourProtocol {

     func someFunction()

}

【讨论】:

  • 好的,那么,我可以创建自己的类,然后无论视图控制器等如何,它都可以在应用程序中使用?这是否相当简单?
  • 是的,当然。您只需创建一个类,在两个控制器中实例化它并在需要时调用该函数。如果函数为两个视图控制器执行通用功能,这是一个很好的做法。
  • 好的,太好了!我一直在学习新事物! :) 我会看看我能找到如何做到这一点。谢谢!
  • 等一下。 @Monomeeth 想要和需要的是 delegationsingleton 看看他的功能是做什么的。它改变了第一个 VC 中的数据。 VC1 和 VC2 都有自己的实例的单独类不会解决他的问题。
  • @Monomeeth 类是语言结构,单例和委托是模式。您通过组合类/协议/属性/方法构建的东西......类本质上只是容器。
【解决方案2】:

要调用 ResetGame(),您需要第一个视图控制器的实例,然后您可以调用 instance.ResetGame()。您可以使用

将第一个视图控制器的实例传递给第二个视图控制器
 override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
            let secondViewController = segue.destinationViewController as! SecondViewController
            destinationVC.instance = self
        }

【讨论】:

  • 错误的数据传递方向;)但这会产生可怕的代码气味。永远不要这样做。使用prepareForSegue 转发数据并创建下降委托模式以将数据传回。
  • @RMenke 当单击第一个视图控制器上的按钮时,我将第一个视图控制器的实例传递给第二个,所以我认为方向是正确的。同意不应该通过视图控制器的实例和下降委托模式会更好。没有包括在内以保持答案简单。
  • @2ank3th 好的,如果我尝试这个,我需要导入某种框架吗?我收到 use of undeclared type 'ProductSKUDetailsTableViewController' 错误。
  • 更新了答案。使用您的第二个视图控制器的名称更改 ProductSKUDetailsTableViewController。
  • @2ank3th 对不起,我一定遗漏了一些明显的东西。我尝试在两个视图控制器中使用代码,并且尝试以不同的顺序做事。我还删除并重新添加了按钮,并编辑了代码以替换视图控制器引用,但无论我做什么我都会遇到问题。我认为问题出在 .instance 位上,但我不太确定。无论如何,谢谢 - 我很感激时间。
猜你喜欢
  • 2017-03-12
  • 1970-01-01
  • 1970-01-01
  • 2017-10-02
  • 2014-07-25
  • 1970-01-01
  • 1970-01-01
  • 2015-12-02
  • 1970-01-01
相关资源
最近更新 更多