首页 > 解决方案 > 在 ViewController 之间传递数据依赖于 UIButton 的标签

问题描述

我已经UITableView并且我正在Item从一个传递UIViewController到另一个。为了实现这一点,我有一系列Item对象。

var array = [Item]()

为了执行segue,我将动作sender参数buttonPressed作为sender方法传递performSegue

@IBAction func buttonPressed(_ sender: UIButton) {
    performSegue(withIdentifier: "identifier", sender: sender)
}

这个按钮在里面UITableViewCell并且有标签等于indexPath.row我在 TableViewcellForRowAt数据源方法中设置的标签:

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    ...
    cell.myButton.tag = indexPath.row
    ...
}

然后在 ViewController 的prepare方法中我向下转换senderUIButton,然后我在目标 ViewController 中分配变量作为selectedItem索引。Itemarraybutton.tag

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if segue.identifier == "identifier" {
        let button = sender as! UIButton
        let destinationVC = segue.destination as! ViewController2
        destinationVC.selectedItem = array[button.tag]
    }
}

问:这很好用,我用了很长时间,但我觉得这不是正确的解决方案。有没有更好的?

标签: swifttableviewsegue

解决方案


我的偏好是在这里使用委托模式。

在这种方法中,视图控制器使自己成为它创建的每个 tableview 单元格的委托。它将 传递Item给单元格。当单元格中的按钮被点击时,单元格将Item返回给视图控制器。通过这种方式,视图控制器知道哪个Item被选中并且应该被发送到下一个视图控制器。

要实现,首先在表格视图单元格中声明一个变量来保存Item

weak var item: Item?

在您的视图控制器中,将项目传递给单元格:

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    //...
    cell.item = array[indexPath.row]
    //...
}

接下来,声明一个委托协议:

protocol ItemSelectionDelegate {
    func itemSelected(_ item: Item)
}

将此类型的变量添加到您的自定义表格视图单元格中,如下所示:

weak var delegate: ItemSelectionDelegate?

使您的表格视图单元格中的按钮在点击时调用委托,并将项目传递给它:

@IBAction func buttonPressed(_ sender: UIButton) {
    if let item = item {
        delegate?.itemSelected(item)
    }
}

现在,让你的视图控制器符合这个协议:

class MyViewController: UIViewController, ..., ItemSelectionDelegate {

    func itemSelected(_ item: Item) {
        //...
    }
}

确保将视图控制器设置为每个单元格的委托:

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    //...
    cell.item = array[indexPath.row]
    cell.delegate = self
    //...
}

调用你的 segue,但传递Item而不是按钮:

class MyViewController: UIViewController, ..., ItemSelectionDelegate {

    func itemSelected(_ item: Item) {
        performSegue(withIdentifier: "identifier", sender: item)
    }
}

现在将其传递给您的下一个视图控制器:

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if segue.identifier == "identifier" {
        let destinationVC = segue.destination as! ViewController2
        destinationVC.selectedItem = sender as? Item
    }
}

这肯定需要更多的设置工作,所以只有在对您有意义的情况下才使用。


推荐阅读