无Storyboard下点击UITableView行弹出UITableViewController问题
问题分析与修正方案
嘿,我来帮你梳理下这段代码里的问题,以及如何正确实现需求~
原代码的核心问题
致命错误:方法嵌套
你把tableView(_:cellForRowAt:)这个UITableView的数据源方法直接嵌套在了tableView(_:didSelectRowAt:)方法内部,这完全不符合iOS的代码规范——系统根本无法识别并调用这个嵌套的方法,因为数据源方法必须是ViewController的顶层成员方法,不能放在其他方法里。弹出的UITableViewController无内容支持
你创建的黄色背景UITableViewController没有设置数据源、代理,也没有注册cell的重用标识符,就算数据源方法写对了,弹出来的tableView也会是空的。cell未显示内容
原代码里拿到name变量后,没有把它赋值给cell的textLabel?.text,所以就算主tableView正常工作,cell也会是空白的。
修正后的实现方案
我分两种方式给你提供代码,一种是快速修改现有代码,另一种是更规范的子类化方式。
方式1:快速修正现有代码
首先,把嵌套的数据源方法移到ViewController的顶层,然后完善弹出逻辑:
// 确保你的ViewController遵守UITableViewDataSource和UITableViewDelegate协议 class YourMainViewController: UIViewController, UITableViewDataSource, UITableViewDelegate { // 假设你的二维数组是这个属性 var twoDimensionalArray: [[String]] = [] // 主tableView实例 var tableView: UITableView! override func viewDidLoad() { super.viewDidLoad() // 初始化主tableView并设置代理、数据源 tableView = UITableView(frame: view.bounds) tableView.dataSource = self tableView.delegate = self // 注册主tableView的cell重用标识符 tableView.register(UITableViewCell.self, forCellReuseIdentifier: "cellId") view.addSubview(tableView) } // 主tableView的点击事件处理 func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { if indexPath.row == 3 { let yellowTableVC = UITableViewController() yellowTableVC.view.backgroundColor = .yellow // 注册弹出tableView的cell重用标识符 yellowTableVC.tableView.register(UITableViewCell.self, forCellReuseIdentifier: "yellowCellId") // 设置数据源和代理为当前VC(需要区分两个tableView的逻辑) yellowTableVC.tableView.dataSource = self yellowTableVC.tableView.delegate = self // 弹出VC present(yellowTableVC, animated: true) } } // 统一处理两个tableView的cell创建逻辑 func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { // 区分是主tableView还是弹出的黄色tableView if tableView == self.tableView { let cell = tableView.dequeueReusableCell(withIdentifier: "cellId", for: indexPath) let name = twoDimensionalArray[indexPath.section][indexPath.row] cell.textLabel?.text = name // 给cell赋值内容 return cell } else { // 弹出的黄色tableView的cell let cell = tableView.dequeueReusableCell(withIdentifier: "yellowCellId", for: indexPath) cell.textLabel?.text = "Yellow Row \(indexPath.row + 1)" return cell } } // 统一处理两个tableView的行数逻辑 func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { if tableView == self.tableView { return twoDimensionalArray[section].count } else { return 5 // 给弹出的tableView设置5行示例内容 } } // 如果有多个section,还需要实现numberOfSections方法 func numberOfSections(in tableView: UITableView) -> Int { return tableView == self.tableView ? twoDimensionalArray.count : 1 } }
方式2:更规范的子类化实现(推荐)
创建一个单独的YellowTableViewController子类,专门处理弹出的黄色tableView,这样代码结构更清晰,避免和主VC的逻辑混在一起:
// 自定义黄色背景的UITableViewController子类 class YellowTableViewController: UITableViewController { override func viewDidLoad() { super.viewDidLoad() view.backgroundColor = .yellow // 注册cell重用标识符 tableView.register(UITableViewCell.self, forCellReuseIdentifier: "yellowCell") } override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return 5 // 自定义行数 } override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "yellowCell", for: indexPath) cell.textLabel?.text = "Yellow Table Row \(indexPath.row + 1)" return cell } } // 主ViewController的实现 class YourMainViewController: UIViewController, UITableViewDataSource, UITableViewDelegate { var twoDimensionalArray: [[String]] = [] var tableView: UITableView! override func viewDidLoad() { super.viewDidLoad() tableView = UITableView(frame: view.bounds) tableView.dataSource = self tableView.delegate = self tableView.register(UITableViewCell.self, forCellReuseIdentifier: "cellId") view.addSubview(tableView) } func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { if indexPath.row == 3 { // 直接实例化自定义的YellowTableViewController let yellowTableVC = YellowTableViewController() present(yellowTableVC, animated: true) } } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "cellId", for: indexPath) let name = twoDimensionalArray[indexPath.section][indexPath.row] cell.textLabel?.text = name return cell } func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return twoDimensionalArray[section].count } func numberOfSections(in tableView: UITableView) -> Int { return twoDimensionalArray.count } }
额外注意事项
- 确保主ViewController已经遵守了
UITableViewDataSource和UITableViewDelegate协议。 - 主tableView的重用标识符必须提前注册(在
viewDidLoad里完成),否则会崩溃。 - 如果你的
twoDimensionalArray是空的,主tableView也会显示空白,记得提前给它赋值数据。
内容的提问来源于stack exchange,提问作者mohammad mohajer
相关产品推荐
相关产品推荐

