You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何不使用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的跳转逻辑

  1. 先删除你提前全局创建的let detailViewController = DetailViewController()代码,避免复用同一实例导致的数据异常
  2. 你当前的代理方法写错了,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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.05 11:06:04