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

Swift中如何向其他UIViewController传值?Swift3无Storyboard MVVM下TableView的didSelectRowAt实现

问题2:Swift3结合MVVM模式(无Storyboard)实现TableView的didSelectRowAt方法?

在MVVM模式下,我们要遵循「UI层管展示和事件捕获,ViewModel管业务逻辑」的原则。结合无Storyboard的场景,我给你整理了完整的实现步骤:

第一步:定义ViewModel,处理数据和业务逻辑

ViewModel负责管理数据源、处理选中行的业务判断,通过闭包通知UI层执行后续操作:

// 自定义数据模型
struct ItemModel {
    let title: String
    let detail: String
}

class ListViewModel {
    // 数据源数组
    var items: [ItemModel] = []
    
    // 闭包:选中行后通知VC做跳转等UI操作
    var onItemSelected: ((ItemModel) -> Void)?
    
    // 模拟加载数据(实际场景可能是网络请求或本地读取)
    func loadData() {
        items = [
            ItemModel(title: "第一个条目", detail: "这是第一条详情"),
            ItemModel(title: "第二个条目", detail: "这是第二条详情")
        ]
    }
    
    // 处理选中行的业务逻辑,比如验证数据合法性
    func handleItemSelection(_ item: ItemModel) {
        // 这里可以添加业务判断,比如是否允许跳转
        onItemSelected?(item)
    }
}

第二步:在ViewController里初始化TableView,绑定数据源与代理

ViewController作为UI层,负责创建TableView、绑定数据源、捕获选中事件,然后将逻辑交给ViewModel处理:

class ListViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
    // 手动初始化TableView(无Storyboard场景)
    private let tableView = UITableView(frame: .zero, style: .plain)
    // 实例化ViewModel
    private let viewModel = ListViewModel()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        setupUI()
        setupViewModel()
    }
    
    private func setupUI() {
        // 设置TableView的约束
        tableView.translatesAutoresizingMaskIntoConstraints = false
        view.addSubview(tableView)
        
        NSLayoutConstraint.activate([
            tableView.topAnchor.constraint(equalTo: view.topAnchor),
            tableView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
            tableView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
            tableView.bottomAnchor.constraint(equalTo: view.bottomAnchor)
        ])
        
        // 设置数据源和代理
        tableView.dataSource = self
        tableView.delegate = self
        // 手动注册cell(无Storyboard场景)
        tableView.register(UITableViewCell.self, forCellReuseIdentifier: "ItemCell")
    }
    
    private func setupViewModel() {
        // 加载数据
        viewModel.loadData()
        // 设置ViewModel的闭包,处理选中后的跳转逻辑
        viewModel.onItemSelected = { [weak self] selectedItem in
            // 创建详情VC并传递选中的数据
            let detailVC = DetailViewController()
            detailVC.selectedItem = selectedItem
            self?.navigationController?.pushViewController(detailVC, animated: true)
        }
        // 数据加载完成后刷新TableView
        tableView.reloadData()
    }
    
    // MARK: - UITableViewDataSource
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return viewModel.items.count
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "ItemCell", for: indexPath)
        let item = viewModel.items[indexPath.row]
        cell.textLabel?.text = item.title
        cell.detailTextLabel?.text = item.detail
        return cell
    }
    
    // MARK: - UITableViewDelegate
    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        // 选中后取消高亮,提升用户体验
        tableView.deselectRow(at: indexPath, animated: true)
        // 获取选中的数据模型
        let selectedItem = viewModel.items[indexPath.row]
        // 交给ViewModel处理业务逻辑
        viewModel.handleItemSelection(selectedItem)
    }
}

// 详情VC示例
class DetailViewController: UIViewController {
    var selectedItem: ItemModel?
    
    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = .white
        title = selectedItem?.title
        // 展示详情数据
        let detailLabel = UILabel(frame: CGRect(x: 20, y: 100, width: view.bounds.width - 40, height: 50))
        detailLabel.text = selectedItem?.detail
        view.addSubview(detailLabel)
    }
}

核心思路说明

  • VC(View层)只负责UI创建、事件捕获(比如didSelectRowAt),不处理业务逻辑;
  • ViewModel负责管理数据源、处理选中行的业务判断,通过闭包通知VC执行UI操作(比如跳转);
  • 这种分离方式让代码更易维护和测试,完全符合MVVM的设计思想。

内容的提问来源于stack exchange,提问作者meggie

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 08:18:28