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
相关产品推荐
相关产品推荐

