【问题标题】:Swift Delegation快速委托
【发布时间】:2023-03-12 16:07:01
【问题描述】:

我在用 Swift 处理委托时遇到了麻烦。在阅读了一些指南之后,我能够在两个 ViewController 之间设置委托,但我不明白它是如何工作的。在我的第一个视图控制器中,我有一个标签,显示在第二个视图控制器中输入的内容,其中包含一个文本字段和一个按钮(返回到第一个视图控制器)。这是第一个视图控制器的代码:

@IBOutlet weak var labelText: UILabel!
func userDidEnterInformation(info: String) {
    labelText.text = info;
}


override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
    if(segue.identifier == "transition"){
        let secondVC: SecondViewController = segue.destinationViewController as! SecondViewController;
        secondVC.delegate = self;

    }    
}

这是第二个视图控制器的代码:

protocol DataEnteredDelegate{
    func userDidEnterInformation(info: String);
}

@IBOutlet weak var userText: UITextField!
var delegate: DataEnteredDelegate? = nil;


@IBAction func buttonPressed(sender: AnyObject) {
    let information = userText.text!;
    delegate!.userDidEnterInformation(information);
    self.navigationController?.popToRootViewControllerAnimated(true);


}

我的理解是,在文本字段中的文本被存储在信息常量中,然后调用协议中的 userDidEnterInformation 方法,该方法在第一个视图控制器中定义。然后,此方法更改第一个视图控制器内的标签。问题是,我不确定 prepareForSegue 函数中发生了什么。具体来说,我不确定 secondVC.delegate = self 的目的是什么。

我将不胜感激任何形式的授权。

【问题讨论】:

  • 顺便说一句,在 Swift 中,您可以在每行的末尾省略分号。这样,您的代码将看起来不那么混乱。 :-)

标签: swift class share delegation


【解决方案1】:

图表很简单,但可以帮助您了解发生了什么。

FirstViewController 必须符合您定义的 DataEnteredDelegate 协议(请参阅 Sumit 的回答)。使用secondVC.delegate = self 时,您是说对于目标为SecondViewController 的segue transition,该SecondViewController 实例的属性delegate 将设置为FirstViewController 的此实例,从而委派事物通过DataEnteredDelegate 协议,从SecondViewController 到您的FirstViewController

【讨论】:

    【解决方案2】:

    您在第二个视图控制器中创建的协议是一个接口。您必须使用 DataEnteredDelegate 协议实现您的第一个视图控制器。

    class FirstViewController:UIViewController, DataEnteredDelegate{
       func userDidEnterInformation(info: String) {
         //stub
       }
    }
    

    【讨论】:

      【解决方案3】:

      如果第二个 VC 的委托未在 prepareForSegue() 中设置,则它仍然是 nil。然后第二个 VC 无法调用第一个 VC。

      附带说明,如果委托是nil,您的代码将崩溃,因为delegate! 正试图解开具有nil 值的可选绑定。最好先解包委托变量:

      if let handler = delegate {
          handler.userDidEnterInformation(information)
      }
      

      或者,您可以使用Swift's Optional Chaining,仅当delegate 不是nil 时才调用userDidEnterInformation

      delegate?.userDidEnterInformation(information);
      

      另外建议声明委托weak,以防止保留循环:

      weak var delegate: DataEnteredDelegate?
      

      【讨论】:

        【解决方案4】:

        代表和协议

        不要试图弄清楚“委托”的字典定义如何与 Swift 中的委托概念相符。没有。

        Swift 中的委托是两个参与者之间的协议——一个感知对象和一个请求对象。 “委托”是“请求对象”。每次看到“委托”时,只要想想“询问者”或“请求者”,它就会更有意义。这是他们的协议...

        传感对象(第二视图控制器):

        我有一些发生的事件的数据。我将发布有关如何访问该数据的说明(协议)。如果你想要它,你必须做三件事。

        1. 您必须在您的类类型中声明您的类遵守我的协议。
        2. 您必须编写我在协议中描述的函数。我不在乎这些函数的作用,但函数类型必须与我发布的内容相匹配。
        3. 在您的代码中,您必须将我的“delegate”(想想“asker”)属性设置为指向您。 {secondVC.delegate = self} 这样我就可以调用您的某个函数来传递数据。

        之后,当我得到一些数据时,我将调用我告诉你编写的对象中的一个函数。我对您的函数的调用将包含您正在寻找的数据作为参数之一。 {delegate!.userDidEnterInformation(information)} 注意:委托! (提问者!)是你。

        委托(请求)对象(第一个视图控制器):

        好的。你达成了协议。

        【讨论】:

          【解决方案5】:

          代表团 您在 Apple 的框架和库中遇到的另一个非常常见的模式是委托。这个概念很简单,它促进了松散耦合和代码可重用性。如果您在应用程序中使用过表视图,那么您已经熟悉委托。表格视图不负责响应用户交互。它将这个任务委托给一个委托对象。当用户点击表格视图中的一行时,表格视图会通知其代理有关此事件。由委托对象(例如视图控制器)决定应用程序应如何响应。”.... 作者 Bart Jacobs

          【讨论】:

          • 嗨 Sachiin,您似乎刚刚从 The Missing Manual For Swift Development Bart Jacobs 复制了大部分内容。你能编辑你的帖子并注明作者吗? Stack Overflow 上并不真正欢迎抄袭,而且在应得的地方给予赞扬总是很好的。祝你好运!
          猜你喜欢
          • 1970-01-01
          • 2016-06-02
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-04-09
          • 2015-01-13
          • 1970-01-01
          • 2020-07-21
          相关资源
          最近更新 更多