在界面构建器中,我在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”,并且通过在另一个表中进行选择来清除两个表的选择。
任何有关如何获得所需结果的见解将不胜感激。如果此处不清楚,请告诉我,我会进行更新。
答案 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)
}
}
}
请随时纠正我的概念和术语。