如何不使用Storyboard编程式点击UITableView行打开ViewController并传参
纯代码实现UITableView点击跳转传值方案
第一步:配置根导航控制器(必备前提)
要实现带返回箭头的跳转效果,必须先把ListViewController嵌套在UINavigationController中作为App的根视图:
- 如果是iOS13及以上使用SceneDelegate的项目,修改
SceneDelegate.swift中的对应方法:
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { guard let windowScene = (scene as? UIWindowScene) else { return } let window = UIWindow(windowScene: windowScene) // 把列表页包装到导航控制器中作为根视图 let rootNav = UINavigationController(rootViewController: ListViewController()) window.rootViewController = rootNav self.window = window window.makeKeyAndVisible() }
- 如果是老版本使用AppDelegate配置根视图的项目,修改
AppDelegate.swift中的对应方法:
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { window = UIWindow(frame: UIScreen.main.bounds) let rootNav = UINavigationController(rootViewController: ListViewController()) window?.rootViewController = rootNav window?.makeKeyAndVisible() return true }
第二步:给DetailViewController新增接收数据的属性
在DetailViewController类中添加属性,用于接收列表页传递过来的用户数据,示例:
import UIKit class DetailViewController: UIViewController { // 新增接收数据的属性 var receivedUser: DataModel? override func viewDidLoad() { super.viewDidLoad() view.backgroundColor = .white // 后续可以用receivedUser的值给页面控件赋值展示 } }
第三步:修改ListViewController的跳转逻辑
- 先删除你提前全局创建的
let detailViewController = DetailViewController()代码,避免复用同一实例导致的数据异常 - 你当前的代理方法写错了,
didDeselectRowAt是取消选中才触发,要替换为didSelectRowAt(点击选中行触发),修改后的扩展代码如下:
extension ListViewController: UITableViewDelegate, UITableViewDataSource { func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return users.count } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: Cells.listCellTablewViewCell) as! ListCellTableViewCell let data = users[indexPath.row] cell.set(data: data) return cell } // 替换为didSelectRowAt方法 func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { // 1. 取出当前行对应的用户数据 let selectedUser = users[indexPath.row] // 2. 创建详情页实例 let detailVC = DetailViewController() // 3. 传递数据 detailVC.receivedUser = selectedUser // 4. 导航控制器跳转,自带返回箭头 navigationController?.pushViewController(detailVC, animated: true) // 可选:点击后取消行的选中状态 tableView.deselectRow(at: indexPath, animated: true) } }
第四步:修正ListCellTableViewCell的现有错误
你的cell代码目前有两个会导致显示异常的问题,修正后代码如下:
import UIKit class ListCellTableViewCell: UITableViewCell { var firstNameLabel = UILabel() var lastNameLabel = UILabel() override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { super.init(style: style, reuseIdentifier: reuseIdentifier) addSubview(firstNameLabel) addSubview(lastNameLabel) configureFirstNameLabel() // 修正:原来重复调用了两次firstName的配置,替换为lastName的配置 configureLastNameLabel() setFirstnameLabel() setLastNameLabel() } required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } func set(data: DataModel) { firstNameLabel.text = data.firstName lastNameLabel.text = data.lastName } func configureFirstNameLabel() { firstNameLabel.numberOfLines = 0 firstNameLabel.backgroundColor = .red } func configureLastNameLabel() { lastNameLabel.numberOfLines = 0 lastNameLabel.adjustsFontSizeToFitWidth = true lastNameLabel.backgroundColor = .blue } func setFirstnameLabel() { firstNameLabel.translatesAutoresizingMaskIntoConstraints = false firstNameLabel.centerYAnchor.constraint(equalTo: centerYAnchor).isActive = true firstNameLabel.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 12).isActive = true firstNameLabel.heightAnchor.constraint(equalToConstant: 30).isActive = true } func setLastNameLabel() { lastNameLabel.translatesAutoresizingMaskIntoConstraints = false lastNameLabel.centerYAnchor.constraint(equalTo: centerYAnchor).isActive = true // 修正:原来写的是对齐自身尾部,改为对齐firstNameLabel的尾部 lastNameLabel.leadingAnchor.constraint(equalTo: firstNameLabel.trailingAnchor, constant: 20).isActive = true lastNameLabel.heightAnchor.constraint(equalToConstant: 30).isActive = true lastNameLabel.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -12).isActive = true } }
内容的提问来源于stack exchange,提问作者beginner992
相关产品推荐
相关产品推荐

