【问题标题】:How to achieve delegation between two ViewController use segue in swift?如何在 swift 中使用 segue 实现两个 ViewController 之间的委托?
【发布时间】:2019-01-18 08:36:39
【问题描述】:

我有点混淆了 swift 中的 abt 委托。比如说,如果我想将 BViewController 中的文本字段的文本传递给 AViewController。 (AViewController 有一个标签,但我没有放任何文本,所以那里什么都没有显示)用户完成输入并单击“LETS GO”按钮后,AViewController 中的标签文本应该显示相同的文本。我实现了代码,但它给了我一些错误。谢谢。

代码:

import UIKit

class AViewController: UIViewController, BViewDelegate {


    @IBOutlet weak var labelTextData: UILabel!

    override func viewDidLoad() {
        super.viewDidLoad()


    }

    func userDoneInput(textData: String) {
        labelTextData.text = textData
    }



}




import UIKit

protocol BViewDelegate{
    func userDoneInput(textData: String)
}

class BViewController: UIViewController {


    @IBOutlet weak var UserInputText: UITextField!
    var bViewDelegate: BViewDelegate?

    override func viewDidLoad() {
        super.viewDidLoad()


    }


    @IBAction func LetsGo(_ sender: UIButton) {
       self.performSegue(withIdentifier: "ShowData", sender: self)

    }

    //use segue
    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        if segue.identifier  == "ShowData" {
            let destination = segue.destination as! AViewController
            destination.labelTextData.text = UserInputText.text

        }
    }

}

【问题讨论】:

  • 您创建了一个循环流。通常,您使用委托将数据从堆栈顶部的视图控制器传递到堆栈下方的视图控制器(A 调用 B,并且您希望将数据从 B 传递回 A)。在您的示例中,您再次堆叠 A(请记住它是一个新实例)并使用 prepare for segue 向前传递数据。在您的示例中,您没有使用委托。

标签: swift segue protocols delegation


【解决方案1】:

1-A节目

2- 当你执行 segue 到 B 时在此处设置委托(此代码在 A 中)

@IBAction func MoveToB (_ sender: UIButton) {
   self.performSegue(withIdentifier: "GoToB", sender: self)

}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if segue.identifier  == "GoToB" {
        let destination = segue.destination as! BViewController
        destination.bViewDelegate = self
    }
}

3- 当你想从 B 回到 A 时(这个代码在 B 里面)

self.bViewDelegate?.userDoneInput(textData: UserInputText.text!)
self.dismiss(animated:true,completion:nil)

4- 从 B 到 A 不应该有任何 segue

【讨论】:

  • Sh_Khan THX,它工作正常,但我并不真正理解你的代码。为什么要使用 self.bViewDelegate?.userDoneInput(textData: UserInputText.text!)?我可以用另一种方式构建 segue,比如从 B -> A 而不是 A-> B?
  • 如果你说 self.AVController?.userDoneInput(textData: UserInputText.text!)? ,如果你从 B -> A 开始,这将导致循环流动在旧的上方再次呈现 A
  • Sh_Khan 我的意思是说,我只保留一个转场 B->A(不管 A 必须首先在应用程序中显示)它仍然有效吗?为什么我们需要一个 segue 来进行委托?或者我们只需要一个 segue 从视图控制器中移动? Sori,我的问题太多了,谢谢
  • 您不需要 segue 进行委派,您可以从 A 呈现/推送 B,其想法是将 B 中的委托链接到 A 中的自我,从一个 VC 移动到您需要的另一个继续/呈现/推动
【解决方案2】:

首先,最好不要使用转场从 A 返回到 B(实际上,您根本没有返回,而是将 A 的新实例放在 B 上)。有多种选择。以下是三个:

  • 使用展开转场。
  • 如果您以模态方式呈现 B,则调用 B 的解除函数(您的图像表明这是您正在执行的操作,但代码中缺少它)。
  • 如果您将 B 作为导航控制器的一部分显示,则调用 B 的 navigationController 的 popViewController(animated:) 方法。

在从 A 呈现 B 之前,您需要将 B 的委托属性设置为 A(您目前没有这样做)。 然后你介绍 B。 然后,当用户在 B 上点击“LET'S GO”时,只需调用 self.dismiss(或替代方法 - 参见上面的选项),还可以调用 self.delegate.userDoneInput(textData:)。

【讨论】:

    【解决方案3】:

    很简单:

    界面生成器设置

    A 有一个您可以在 B 中编辑的标签。有两个按钮可让您来回导航。重要的是,您不要按住 Ctrl 键并单击“返回 A”按钮以转到 A。这样做会将另一个控制器添加到您的层次结构中:A 呈现 B,而 B 呈现 另一个 A。相反, B 应该关闭自己以显示原来的 A(参见下面的代码)。

    代码

    //
    // AViewController.swift
    //
    class AViewController: UIViewController {
        @IBOutlet weak var label: UILabel!
    
        override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
            if segue.identifier == "gotoB", let bController = segue.destination as? BViewController {
                // Give B a chance to finish loading before using its outlets
                bController.loadViewIfNeeded()
                bController.textField.text = label.text
                bController.delegate = self
            }
        }
    }
    
    extension AViewController: BViewControllerDelegate {
        // B says that it has ended. We now update the label in A
        func bViewControllerDidEnd(_ controller: BViewController, textValue: String) {
            label.text = textValue
        }
    }
    
    //
    // BViewController.swift
    //
    protocol BViewControllerDelegate {
        // For delegate methods, it's customary to pass in the object that triggers this delegate
        // (the BViewController), in case you need to make use of its other properties
        func bViewControllerDidEnd(_ controller: BViewController, textValue: String)
    }
    
    class BViewController: UIViewController {
        @IBOutlet weak var textField: UITextField!
        var delegate: BViewControllerDelegate?
    
        @IBAction func goBackToA(_ sender: Any) {
            // Tell the delegate that "I'm done"
            delegate?.bViewControllerDidEnd(self, textValue: textField.text!)
    
            // Dismiss B, not segue to another instance of A
            self.dismiss(animated: true)
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2018-12-19
      • 1970-01-01
      • 2015-09-13
      • 1970-01-01
      • 1970-01-01
      • 2016-03-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多