我无法通过协议在视图控制器之间传递数据

时间:2019-01-13 09:30:27

标签: swift

视图控制器A

class ViewController: UIViewController {

    var delegate: server?

    override func viewDidLoad() {
        super.viewDidLoad()
    }

    @IBAction func ok(_ sender: Any) {
        delegate?.datum(data: "sd")
        performSegue(withIdentifier: "goingB", sender: self)
    }

}

视图控制器B

protocol server {
    func datum(data: String)
}

class ViewControllerB: UIViewController, server {

    @IBOutlet weak var label: UILabel!

    override func viewDidLoad() {
        super.viewDidLoad()    
    }

    func datum(data: String) {
        self.label.text = data
        print(data)
    }

}

我需要通过视图控制器传递数据,但是我无法传递,但是我知道我们可以通过协议传递数据,但是无论如何,当我尝试运行程序时,最终都会出错

2 个答案:

答案 0 :(得分:1)

如果您需要将数据从一个视图控制器传递到另一个视图控制器,并且您正在使用segue来展示新的视图控制器,则只需覆盖prepare(for:sender:),就无需使用委托。在这里,您可以获取将要显示的控制器的参考,还可以分配其变量。

因此,首先在第二个视图控制器中创建变量,并声明如果您给它分配新值,它将更改标签的文本

class ViewControllerB: UIViewController {

    @IBOutlet weak var label: UILabel!

    var variable: String? {
        didSet {
            label.text = variable
        }
    }
}

现在,在第一个视图控制器中,将覆盖prepare(for:sender:),如果已经执行了segue,则向下转换目标视图控制器并分配其变量

class ViewController: UIViewController {

    @IBAction func ok(_ sender: Any) {
        performSegue(withIdentifier: "goingB", sender: self)
    }

    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        if segue.identifier == "goingB" {
            let destinationVC = segue.destination as! ViewControllerB
            destinationVC.variable = "sd"
        }
    }

}

无论如何,如果要将代码与委托一起使用,则必须将第一个视图控制器的委托设置为将要显示的第二个视图控制器。为此,您还可以使用prepare(for:sender:)来获取segue目的地的引用,然后可以在委托上调用方法

class ViewController: UIViewController {

    var delegate: server?

    @IBAction func ok(_ sender: Any) {
        performSegue(withIdentifier: "goingB", sender: self)
    }

    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        if segue.identifier == "goingB" {
            let destinationVC = segue.destination as! ViewControllerB
            delegate = destinationVC
            delegate?.datum(data: "sd")
        }
    }

}

注意:

  • 使用大写字母Server的名称协议,我们正在讨论代表,请添加代表词:ServerDelegate
  • 仅针对类的约束协议
  • 然后使您的委托变量weak

protocol ServerDelegate: class {
    func datum(data: String)
}

...

weak var delegate: ServerDelegate?

答案 1 :(得分:0)

最简单的方法是直接在prepare中设置属性。

但是,如果要使用委托,则可以。您的问题是您在A和B之间混在一起。 编写方式,当您调用委托?.datum时,未定义委托,因此我们无法访问基准。 你想让我做什么 ?从A转到B,然后在B中,使用从A接收到的数据更新B中的标签。
这里只是为了演示如何使用(但是与直接分配相比显然太复杂了。)

protocol Server {
    func datum() -> String
}

class ViewControllerB: UIViewController {

    @IBOutlet weak var label: UILabel!

    var delegate: Server?

    override func viewDidLoad() {
        super.viewDidLoad()
        let data = delegate?.datum()
        self.label.text = data
    }


}

class ViewControllerA: UIViewController, Server {

    override func viewDidLoad() {
        super.viewDidLoad()
    }

    var data = "sd"

    func datum() -> String {
        return data
    }

    @IBAction func ok(_ sender: Any) {
        performSegue(withIdentifier: "goingB", sender: self)
    }

    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        if let destVC = segue.destination as? ViewControllerB {
            destVC.delegate = self
        }
    }
}