Swift开发:选中TableViewCell无法执行Segue跳转求助
我Swift开发经验不多,正在写代码学习。我的应用初始界面有多个按钮,点击可跳转到不同页面/功能,其中“Table View (CH Cantons)”按钮会打开一个带UITableView的视图,这个TableView要展示三个内容:
- 州徽/州盾形纹章
- 州名称(示例:ZH - Zurich)
- 对应州的面积
选中州的单元格时,应该跳转到新页面展示该州详情,但试了好几种方法都没实现。另外想问:TableView必须放在主视图里吗?
相关代码
生成TableView的代码
let cantonsData = ["AG - Aargau","BE - Bern","GE - Geneve","GR - Graubunden","JU - Jura","LU - Lucern","NE - Neuchâtel","SG - Sankt Gallen","TG - Thurgau","TI - Ticino","UR - Uri","VD - Vaud","VS - Valais","ZH - Zurich","AI - Appenzell \n Innerrhoden","AR - Appenzell \n Ausserrhoden","SH - Schaffhausen","BL - Basel \n Landschaft","BS - Basel","SO - Solothurn","FR - Fribourg","ZG - Zug","GL - Glarus","NW - Nidwald","OW - Obwald", "SZ - Schwyz"] let area = ["Area (km2): 1404 km2","Area (km2): 5,960 km2","Area (km2): 1,792 km2","Area (km2): 7,105 km2","Area (km2): 839 km2","Area (km2): 1,494 km2","Area (km2): 802 km2 ","Area (km2): 2031 km2","Area (km2): 992 km2","Area (km2): 2812 km2","Area (km2): 1077 km2","Area (km2): 3212 km2","Area (km2): 5224 km2","Area (km2): 1729 km2","Area (km2): 172 km2","Area (km2): 243 km2","Area (km2): 298 km2","Area (km2): 518 km2","Area (km2): 37 km2","Area (km2): 790 km2","FR - Fribourg","ZG - Zug","GL - Glarus","NW - Nidwald","OW - Obwald", "SZ - Schwyz"] override var modalPresentationStyle: UIModalPresentationStyle { get { .fullScreen } set { assertionFailure("Shouldnt change that 😠") } } override func viewDidLoad() { //super.viewDidLoad() // Do any additional setup after loading the view, typically from a nib. self.title = "CH Cantons / CH Kantons" tableView.dataSource = self tableView.delegate = self let nibName = UINib(nibName: "TableViewCell", bundle: nil) tableView.register(nibName, forCellReuseIdentifier: "tableViewCell") } func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return cantonsData.count } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "tableViewCell", for: indexPath) as! TableViewCell cell.commonInit("CH-\(indexPath.item+1)", title: cantonsData[indexPath.item], sub: area[indexPath.item]) return cell } func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { return 180 }
单元格点击跳转代码(第一种尝试)
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { let storyboard = UIStoryboard(name: "TableViewCH", bundle: nil) if let vc = storyboard.instantiateViewController(withIdentifier: "DetailViewController") as? DetailViewController{ vc.img = UIImage(named: cantonsData[indexPath.item])! vc.canton = cantonsData[indexPath.row] self.navigationController?.pushViewController(vc, animated: true) } }
第二种尝试代码
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: IndexPath) { let cell = tableView.cellForRow(at: indexPath) tableView.deselectRow(at: indexPath, animated: true) performSegue(withIdentifier: "mySegue", sender: cell) }
问题解答
关于TableView的位置疑问
TableView不需要必须放在主视图里,它可以放在任何UIViewController的视图层级中,只要正确设置数据源和代理,就能正常运行。
跳转失败的原因排查及解决办法
第一种跳转方法的问题
导航控制器为空
你重写了modalPresentationStyle为全屏,说明当前TableView所在的VC是被modal出来的,不在导航栈中,调用navigationController?.pushViewController会直接失效。
解决:要么用UINavigationController包裹这个VC后再modal,要么把跳转方式改为present(vc, animated: true)。图片资源加载崩溃
UIImage(named: cantonsData[indexPath.item])!用州名称字符串作为图片名,若文件名不匹配会返回nil,强行解包!会导致崩溃,中断跳转流程。
解决:改用州代码(从cantonsData提取前两位)作为图片名,同时安全解包:if let imageName = cantonsData[indexPath.item].components(separatedBy: " - ").first, let image = UIImage(named: imageName) { vc.img = image }Storyboard或VC标识符错误
确认UIStoryboard(name: "TableViewCH")的名称和实际storyboard文件名完全一致(注意大小写),同时DetailViewController的storyboard ID已正确设置。
第二种跳转方法的问题
方法签名错误
Swift 3及以后,单元格点击方法的正确签名是func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath),你写的旧版本签名不会被系统调用,导致点击无反应。缺少Segue数据传递逻辑
用performSegue跳转时,必须实现prepare(for:sender:)方法传递数据:override func prepare(for segue: UIStoryboardSegue, sender: Any?) { guard segue.identifier == "mySegue", let detailVC = segue.destination as? DetailViewController, let indexPath = tableView.indexPathForSelectedRow else { return } detailVC.canton = cantonsData[indexPath.row] if let imageName = cantonsData[indexPath.row].components(separatedBy: " - ").first, let image = UIImage(named: imageName) { detailVC.img = image } }Segue配置错误
确认storyboard中segue的标识符为"mySegue",且segue是从当前TableViewVC指向DetailVC(或从单元格指向DetailVC)。
通用检查项
- 确认
tableView.delegate = self未被其他代码覆盖; - 检查TableViewCell的
Selection属性不是None(需设为Default或Gray)。
内容的提问来源于stack exchange,提问作者Vitor Ferreira

