简体   繁体   English

为什么我必须调用我的协议函数两次才能使其工作?

[英]Why do I have to call my protocol functions two times to make it work?

I'm currently building a simple app to learn the protocol - delegate functionality.我目前正在构建一个简单的应用程序来学习协议 - 委托功能。 However my code doesn't work, even after I edited the way I did in my first practice app where it worked.然而,我的代码不起作用,即使我按照我在第一个练习应用程序中所做的方式进行了编辑。 In the FirstViewController there is a UILabel and a UIButton .FirstViewController中有一个UILabel和一个UIButton When the user taps on the UIButton , a segue brings them to the SecondViewController where they should enter their name into a UITextField .当用户点击UIButton时,一个 segue 将他们带到SecondViewController ,他们应该在其中将他们的名字输入到UITextField中。 After that, they can press the UIButton in the SecondViewController and the entered Name should be displayed in the UILabel in the FirstViewController .之后,他们可以在UIButton中按SecondViewController ,输入的名称应该显示在FirstViewControllerUILabel中。

I can't figure out why I have to call the protocol function two times in the @IBAction backButtonPresses() .我不明白为什么我必须在@IBAction backButtonPresses()中调用协议 function 两次。 Also, I can't figure out how to handle the same protocol function in the FirstViewController .另外,我无法弄清楚如何在 FirstViewController 中处理相同的协议FirstViewController

Here's the code for the FirstViewController.swift file:这是FirstViewController.swift文件的代码:

import UIKit

class FirstViewController: UIViewController, SecondViewControllerDelegate {
    
    
    @IBOutlet weak var nameLabel: UILabel!
    @IBOutlet weak var button: UIButton!
    
    var labelText = ""
    let secondVC = SecondViewController()
    
    
    func changeLabelText(name: String) {
        labelText = secondVC.enteredName
    }
    
    
    @IBAction func buttonPressed(_ sender: UIButton) {
        performSegue(withIdentifier: "goToSecondVC", sender: self)
    }
    
    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        let destinationVC = segue.destination as? SecondViewController
        destinationVC?.delegate = self
    }
    
    
    override func viewDidLoad() {
        super.viewDidLoad()
        nameLabel.text = secondVC.enteredName
    }
    
}

And here's the code of the secondViewController :这是secondViewController的代码:

import UIKit

protocol SecondViewControllerDelegate {
    func changeLabelText(name: String)
}

class SecondViewController: UIViewController, SecondViewControllerDelegate {
    
    
    var delegate: SecondViewControllerDelegate?
    
    @IBOutlet weak var nameTextField: UITextField!
    @IBOutlet weak var backButton: UIButton!
    
    var enteredName: String = ""
    
    func changeLabelText(name: String) {
        enteredName = name
    }

    @IBAction func backButtonPressed(_ sender: UIButton) {
        changeLabelText(name: nameTextField.text ?? "")
        delegate?.changeLabelText(name: nameTextField.text ?? "")
        print("das ist der name \(enteredName)")
        dismiss(animated: true)
    }
    
    
    override func viewDidLoad() {
        super.viewDidLoad()
    }
}

You do not call any delegate method twice in backButtonPressed .您不会在backButtonPressed中两次调用任何委托方法。 You are calling two completely different changeLabelText methods.您正在调用两个完全不同changeLabelText方法。 One is in SecondViewController , the other is on the delegate.一个在SecondViewController中,另一个在委托中。

The call to changeLabelText in the SecondViewController is quite unnecessary.changeLabelText中调用SecondViewController是完全没有必要的。 In fact, the enteredName property in SecondViewController is unnecessary.其实SecondViewController中的enteredName属性是没有必要的。 Also, SecondViewController should not be implementing its own delegate.此外, SecondViewController不应实现自己的委托。

The call to changeLabelText on delegate is all you need.您只需要在delegate上调用changeLabelText You just need to update the implementation of changeLabelText in FirstViewController to update the label's text with the new value.您只需要在FirstViewController中更新changeLabelText的实现,以使用新值更新标签的文本。

func changeLabelText(name: String) {
    nameLabel.text = name
}

Do not reference the secondVC property in FirstViewController .不要在FirstViewController中引用secondVC属性。 In fact, remove that property completely.事实上,完全删除该属性。 It's not needed and it's referencing a completely different instance of SecondViewController than the one you actually present via segue.它不是必需的,它引用的SecondViewController实例与您通过 segue 实际呈现的实例完全不同。

I also suggest renaming the delegate method from changeLabelText to something more general such as enteredText .我还建议将委托方法从changeLabelText重命名为更通用的名称,例如enteredText SecondViewController can be used by any other view controller to obtain some text.任何其他视图SecondViewController都可以使用 SecondViewController 来获取一些文本。 It's not specific to changing a label.它不特定于更改 label。

Here's your two view controllers with suggested changes:这是带有建议更改的两个视图控制器:

class FirstViewController: UIViewController, SecondViewControllerDelegate {
    @IBOutlet weak var nameLabel: UILabel!
    @IBOutlet weak var button: UIButton!
    
    func enteredText(name: String) {
        nameLabel.text = name
    }
    
    @IBAction func buttonPressed(_ sender: UIButton) {
        performSegue(withIdentifier: "goToSecondVC", sender: self)
    }
    
    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        let destinationVC = segue.destination as? SecondViewController
        destinationVC?.delegate = self
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
    }
}
protocol SecondViewControllerDelegate {
    func enteredText(name: String)
}

class SecondViewController: UIViewController {
    var delegate: SecondViewControllerDelegate?
    
    @IBOutlet weak var nameTextField: UITextField!
    @IBOutlet weak var backButton: UIButton!
    
    @IBAction func backButtonPressed(_ sender: UIButton) {
        let name = nameTextField.text ?? ""
        delegate?.changeLabelText(name: name)
        print("das ist der name \(name)")
        dismiss(animated: true)
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM