如何在UITableViewController的两个并排实例之间传递数据

时间:2019-06-23 15:53:47

标签: ios swift uitableview delegation

在界面构建器中,我在UIStackView的容器视图中嵌入了UITableViewController的两个实例。两个TableViewControllers都链接到相同的自定义类文档(请参见下面的代码)。它们之间的唯一区别在于它们显示的数据。两者都具有允许多个选择的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")
        }
    }
}

运行以上命令并点击其中一个表会在控制台上打印“ Unidentified Table View”,并且通过在另一个表中进行选择来清除两个表的选择。

任何有关如何获得所需结果的见解将不胜感激。如果此处不清楚,请告诉我,我会进行更新。

1 个答案:

答案 0 :(得分:0)

通过委派在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)
        }
    }
}

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