【问题标题】:How to Pass Data Between Two Side-by-Side Instances of a UITableViewController如何在 UITableViewController 的两个并排实例之间传递数据
【发布时间】:2019-11-05 14:36:46
【问题描述】:

在界面生成器中,我在 UIStackView 的容器视图中嵌入了 UITableViewController 的两个实例。两个 TableViewController 都链接到同一个自定义类文档(参见下面的代码)。它们之间的唯一区别在于它们显示的数据。两者都有允许多选的 UITableViews - 但我也希望选择一个表中的任何内容会导致取消选择另一个表中的所有内容,反之亦然。我尝试使用委托进行设置,但我不知道如何在 UITableViewController 中从另一个实例引用一个实例,以将每个实例分配为另一个实例的委托。

除了子类名称之外,我找不到任何关于委托或关于通过任何其他方式引用视图控制器的相关信息。所以在我最近的尝试中,我尝试引用父对象的另一个子对象。以下是相关代码:

protocol TableViewSelectionDelegate: AnyObject {
    func didSelectInTableView(_ tableView: UITableView)
}

class TableViewController: UITableViewController, TableViewSelectionDelegate {

    weak var delegate: TableViewSelectionDelegate?

    @IBOutlet var numbersTableView: UITableView!
    @IBOutlet var lettersTableView: UITableView!

    // Received by segue
    var displayables: [Character] = []

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

    // (It's too soon to determine parents/children in viewDidLoad())
    override func viewWillAppear(_ animated: Bool) {

        guard let tableViewControllers = parent?.children else {
            print("No tableViewControllers found!")
            return
        }

        switch restorationIdentifier {

        case "NumbersTableViewController":
            for tableViewController in tableViewControllers {
                if tableViewController.restorationIdentifier == "LettersTableViewController" {
                    delegate = tableViewController as? TableViewSelectionDelegate
                }
            }

        case "LettersTableViewController":
            for tableViewController in tableViewControllers {
                if tableViewController.restorationIdentifier == "NumbersTableViewController" {
                    delegate = tableViewController as? TableViewSelectionDelegate
                }
            }

        default: print("Unidentified Table View Controller")
        }
    }

    override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        delegate?.didSelectInTableView(tableView)
    }

    func didSelectInTableView(_ tableView: UITableView) {

        switch tableView {

        case numbersTableView:
            numbersTableView.indexPathsForSelectedRows?.forEach { indexPath in
                numbersTableView.deselectRow(at: indexPath, animated: false)
            }

        case lettersTableView:
            lettersTableView.indexPathsForSelectedRows?.forEach { indexPath in
                lettersTableView.deselectRow(at: indexPath, animated: false)
            }

        default: print("Unidentified Table View")
        }
    }
}

运行上述程序并在任一表中点击会导致控制台打印“未识别的表视图”,并且通过在另一个表中进行选择来清除两个表的选择。

任何关于如何获得我想要的结果的见解将不胜感激。如果这里有什么不清楚的地方,请告诉我,我会更新。

【问题讨论】:

    标签: ios swift uitableview delegation


    【解决方案1】:

    通过委托在 UITableViewController 的两个实例之间传递信息显然不像最初看起来那么复杂。唯一值得注意的部分是代表的设置。在自定义 TableViewController 类中,当一个实例初始化时,它需要将自己设置为另一个实例的委托。就是这样!

    在这种情况下,要从另一个实例中引用一个实例,可以使用 tableViewController 的父级来访问另一个子 tableViewController。尽管可能有更好的方法来做到这一点,但请参阅我的特定解决方案的代码。值得注意的是,由于在 viewDidLoad() 之后还没有设置父属性,所以我需要在 viewWillAppear() 中进行设置。另请注意,此方法不需要使用 restoreIdentifiers 或标签。而是通过其 tableView 属性间接确定 tableViewController 实例。

    委托的 didSelectInTableView() 函数传递在另一个 tableViewController 实例中选择的 selectedInTableView。由于委托需要清除自己选择的行,因此不需要 selectedInTableView 用于此目的。也就是说,对于只是清除行,该函数不需要传递任何内容。

    protocol TableViewSelectionDelegate: AnyObject {
        func didSelectInTableView(_ selectedInTableView: UITableView)
    }
    
    class TableViewController: UITableViewController, TableViewSelectionDelegate {
    
        weak var delegate: TableViewSelectionDelegate?
    
        // Received by segue
        var displayables: [Character] = []
    
        override func viewDidLoad() {
            super.viewDidLoad()
        }
    
        // (It's too soon to determine parents/children in viewDidLoad())
        override func viewWillAppear(_ animated: Bool) {
    
            guard let siblingTableViewControllers = parent?.children as? [TableViewController] else { return }
    
            switch tableView {
    
            case siblingTableViewControllers[0].tableView: siblingTableViewControllers[1].delegate = self
            case siblingTableViewControllers[1].tableView: siblingTableViewControllers[0].delegate = self
    
            default: print("Unidentified Table View Controller")
            }
        }
    
        override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    
            delegate?.didSelectInTableView(tableView)
        }
    
        func didSelectInTableView(_ selectedInTableView: UITableView) {
    
            // selectedTableView is NOT the one that needs to be cleared
            // The function only makes it available for other purposes
    
            tableView.indexPathsForSelectedRows?.forEach { indexPath in
                tableView.deselectRow(at: indexPath, animated: false)
            }
        }
    }
    

    请随时纠正我的概念和术语。

    【讨论】:

      猜你喜欢
      • 2013-01-25
      • 2014-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-05-21
      • 1970-01-01
      • 2018-09-25
      相关资源
      最近更新 更多