如何在UITableViewDataSource为ViewModel时将Cell的delegate设为所属ViewController
解决方案
你可以通过在ViewModel中新增透传代理属性的方式实现需求,无需破坏现有分层逻辑,具体修改步骤如下:
步骤1:为FeedViewModel新增Cell代理持有属性
在FeedViewModel类中添加一个弱引用的Cell代理属性,用来存储外部传入的ViewController实例,避免循环引用:
public class FeedViewModel: NSObject { var feed: Feed? weak var delegate: FeedViewModelDelegate? // 新增:Cell代理透传属性 weak var cellDelegate: PostHeaderTableViewCellDelegate? // 原有其他代码保持不变 }
步骤2:修改cellForRowAt中的代理赋值逻辑
把原来指向FeedViewModelDelegate的赋值,改成指向新增的cellDelegate属性:
public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: PostHeaderTableViewCell.identifier, for: indexPath) as! PostHeaderTableViewCell cell.configure(with: postViewModel.header.goer, event: postViewModel.header.event) // 修改此处的代理赋值 cell.delegate = cellDelegate return cell }
步骤3:让FeedViewController遵守并实现Cell代理协议
首先在FeedViewController的viewDidLoad中给ViewModel的cellDelegate属性赋值为自身:
override func viewDidLoad() { super.viewDidLoad() view.backgroundColor = .systemBackground feedViewModel.delegate = self // 新增:将自身赋值给ViewModel的Cell代理属性 feedViewModel.cellDelegate = self tableView.delegate = self tableView.dataSource = feedViewModel feedViewModel.fetchData() }
然后新增协议实现扩展,处理Cell的交互事件:
extension FeedViewController: PostHeaderTableViewCellDelegate { func postHeaderTableViewCellDidTapMore() { // 实现点击更多按钮的业务逻辑 } func postHeaderTableViewCellDidTapUsername(goer: Goer?) { // 实现点击用户名的业务逻辑 } func postHeaderTableViewCellDidTapEventName(event: Event?) { // 实现点击活动名称的业务逻辑 } func postHeaderTableViewCellDidTapProfilePicture(goer: Goer?) { // 实现点击头像的业务逻辑 } }
方案说明
该实现完全符合MVVM分层规则:ViewModel仅负责数据提供和列表渲染逻辑,UI交互事件全部由ViewController层处理,所有代理均使用弱引用,不会产生循环引用问题。
内容的提问来源于stack exchange,提问作者Sebby Fay
相关产品推荐
相关产品推荐

