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

Viper架构中处理UICollectionViewCell交互事件的最佳实现方案是什么

Viper架构下UICollectionViewCell交互事件实现方案

核心规则:Viper中所有用户交互事件最终由Presenter处理,Cell、ViewController都属于View层,仅负责事件捕获和转发,不包含任何业务逻辑。


1. 定义Cell的事件出口

可以选择闭包或者代理两种方式,这里优先推荐更简洁的闭包方案,替换MVC中Cell的代理协议:

class StoriesCollectionViewCell: UICollectionViewCell {
    var story: Story?
    // 点击事件回调,将需要的参数对外抛出
    var didTapUserCallback: ((User) -> Void)?
    
    // 内部捕获Cell上的点击事件,比如用户头像的点击手势触发后调用
    @objc private func userAvatarTapped() {
        guard let user = story?.user else { return }
        didTapUserCallback?(user)
    }
}

如果习惯用代理实现,逻辑和MVC中一致,只是代理的实现方ViewController收到事件后不处理,直接转发即可。

2. 扩展Presenter的输入协议,新增事件处理方法

在StoriesPresenterInput协议中新增对应交互的处理入口:

protocol StoriesPresenterInput: AnyObject {
    func viewDidLoad()
    // 新增处理用户点击事件的方法
    func didSelectUser(user: User)
}

3. ViewController绑定Cell事件,转发给Presenter

修改cellForItemAt方法,绑定Cell的回调,收到事件后直接转发给Presenter:

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "storiesCell", for: indexPath) as! StoriesCollectionViewCell
    cell.story = stories[indexPath.item]
    // 注意加[weak self]避免循环引用
    cell.didTapUserCallback = { [weak self] user in
        self?.presenter?.didSelectUser(user: user)
    }
    return cell
}

4. Presenter实现业务逻辑

Presenter中实现对应的事件处理方法,根据业务需求调用Router做页面跳转,或者调用Interactor做数据请求、埋点等操作:

class StoriesPresenter: StoriesPresenterInput {
    weak var view: StoriesViewOutput?
    var router: StoriesRouterProtocol?
    var interactor: StoriesInteractorInput?
    
    func didSelectUser(user: User) {
        // 示例1:调用路由跳转到用户主页
        router?.pushToUserProfilePage(user: user)
        // 示例2:调用交互器记录点击埋点
        interactor?.trackUserClickEvent(user: user)
    }
}

优化建议

如果Cell上有多个交互事件(比如点赞、点击内容、点击用户),可以把事件封装成枚举统一传递,避免定义多个闭包属性:

// 定义Cell所有的交互事件类型
enum StoryCellAction {
    case tapUser(User)
    case tapLike(Story)
    case tapContent(Story)
}

// Cell中统一用一个回调传递事件
var actionCallback: ((StoryCellAction) -> Void)?

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.29 04:57:02