Как передать данные между двумя параллельными экземплярами UITableViewController - PullRequest
0 голосов
/ 23 июня 2019

В построителе интерфейса я встроил два экземпляра UITableViewController в представления контейнера в UIStackView. Оба TableViewControllers связаны с одним и тем же документом пользовательского класса (см. Код ниже). Единственная разница между ними заключается в данных, которые они отображают. Оба имеют UITableView, которые допускают множественный выбор, но я также хочу, чтобы выбор чего-либо в одной таблице приводил к отмене выбора всего в другой таблице, и наоборот. Я попытался настроить это с делегированием, но я не знаю, как ссылаться на один экземпляр из другого в 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")
        }
    }
}

Выполнение вышеуказанного и нажатие на любую из таблиц приводит к тому, что «Неопознанное табличное представление» выводится на консоль, и ни одна из таблиц не очищается при выборе другой в другой.

Любое понимание того, как я могу получить желаемые результаты, будет оценено. Если что-то здесь неясно, дайте мне знать, и я сделаю обновления.

1 Ответ

0 голосов
/ 28 июня 2019

Передача информации между двумя экземплярами UITableViewController через делегирование, очевидно, не так сложна, как поначалу казалось.Единственная заслуживающая внимания часть - это настройка делегата.Внутри пользовательского класса TableViewController, когда один экземпляр инициализируется, он должен установить себя в качестве делегата другого экземпляра.Вот и все!

В этом случае, чтобы ссылаться на один экземпляр из другого, можно использовать родительский элемент tableViewController, чтобы перейти к другому дочернему элементу tableViewController.Хотя может быть лучший способ сделать это, посмотрите код моего конкретного решения.Примечательно, что так как родительское свойство еще не установлено сразу после viewDidLoad (), мне нужно было настроить все в viewWillAppear ().Также обратите внимание, что этот подход не требует использования restoreIdentifiers или тегов.Скорее, он косвенно определяет экземпляр tableViewController через свое свойство tableView.

Делегированная функция didSelectInTableView () передает selectedInTableView, который был выбран в другом экземпляре tableViewController.Поскольку делегату необходимо очистить свои собственные выбранные строки, 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)
        }
    }
}

Пожалуйста, не стесняйтесь исправлять мою концептуализацию и терминологию.

...