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

Swift复用Cell中Storyboard按钮触发多次事件问题

问题分析与解决方案

问题根源

UITableView的cell采用复用机制,每次cellForRowAt调用时,你都会给button_seeAll添加新的点击事件,但没有移除之前绑定的旧事件。随着cell被反复复用,同一个按钮会绑定多个不同的action,点击时就会触发多个跳转逻辑。

解决方法

方法一:移除旧Target后再添加新绑定

在每个section的cell配置中,先清除按钮上所有已绑定的事件,再添加当前section对应的Target:

修改后的cellForRowAt关键代码片段:

// section 1(Top Picks)的cell配置
let cell = tableView.dequeueReusableCell(withIdentifier: "flashDealCell", for: indexPath) as! flashDealCell
// 先移除所有旧的事件绑定
cell.button_seeAll.removeTarget(nil, action: nil, for: .allEvents)
// 再添加当前对应的事件
cell.button_seeAll.addTarget(self, action: #selector(SeeAllFeaturedProduct), for: .touchUpInside)
// 其他配置代码...

// section 2(New Releases)的cell配置
let cell = tableView.dequeueReusableCell(withIdentifier: "flashDealCell", for: indexPath) as! flashDealCell
cell.button_seeAll.removeTarget(nil, action: nil, for: .allEvents)
cell.button_seeAll.addTarget(self, action: #selector(SeeAllNewArrivalsProduct), for: .touchUpInside)
// 其他配置代码...

// section 3(Recommended)的cell配置
let cell = tableView.dequeueReusableCell(withIdentifier: "flashDealCell", for: indexPath) as! flashDealCell
cell.button_seeAll.removeTarget(nil, action: nil, for: .allEvents)
cell.button_seeAll.addTarget(self, action: #selector(SeeAllFlashDealsProduct), for: .touchUpInside)
// 其他配置代码...

方法二:统一事件处理(更优解)

给flashDealCell添加一个分类类型的属性,按钮只绑定一个通用action,通过cell的类型区分跳转逻辑,避免重复绑定:

  1. 先给cell添加枚举和属性:
enum ProductCategory {
    case topPicks
    case newReleases
    case recommended
}

class flashDealCell: UITableViewCell {
    // 已有的IBOutlet...
    var category: ProductCategory?
}
  1. 修改cellForRowAt配置:
// section 1
let cell = tableView.dequeueReusableCell(withIdentifier: "flashDealCell", for: indexPath) as! flashDealCell
cell.category = .topPicks
cell.button_seeAll.removeTarget(nil, action: nil, for: .allEvents)
cell.button_seeAll.addTarget(self, action: #selector(seeAllProducts(_:)), for: .touchUpInside)
// 其他配置...

// section 2
let cell = tableView.dequeueReusableCell(withIdentifier: "flashDealCell", for: indexPath) as! flashDealCell
cell.category = .newReleases
cell.button_seeAll.removeTarget(nil, action: nil, for: .allEvents)
cell.button_seeAll.addTarget(self, action: #selector(seeAllProducts(_:)), for: .touchUpInside)
// 其他配置...

// section 3
let cell = tableView.dequeueReusableCell(withIdentifier: "flashDealCell", for: indexPath) as! flashDealCell
cell.category = .recommended
cell.button_seeAll.removeTarget(nil, action: nil, for: .allEvents)
cell.button_seeAll.addTarget(self, action: #selector(seeAllProducts(_:)), for: .touchUpInside)
// 其他配置...
  1. 编写统一的处理方法:
@objc func seeAllProducts(_ sender: UIButton) {
    guard let cell = sender.superview?.superview as? flashDealCell, let category = cell.category else { return }
    
    let vc = UIStoryboard(name: "Product", bundle: nil).instantiateViewController(withIdentifier: "FlashDealsVC") as! FlashDealsVC
    
    switch category {
    case .topPicks:
        vc.headerText = "Top Picks"
        print("Clicked on Top Picks")
    case .newReleases:
        vc.headerText = "New Releases"
        print("Clicked on New Releases")
    case .recommended:
        vc.headerText = "Recommended"
        print("Clicked on Recommended")
    }
    
    self.navigationController?.pushViewController(vc, animated: true)
}

注意事项

UITableViewCell复用时,所有动态设置的内容(事件、文本、UI显示状态等)都要确保重置,避免旧的配置残留影响新的cell展示和交互逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 03:13:23