Swift情节提要操作在可重用单元上触发多个操作

3duebb1j  于 2023-03-16  发布在  Swift
关注(0)|答案(2)|浏览(132)

我不知道用什么好的方式来描述这一点,但基本上,当我在由同一个可重用单元格组成的表格视图中单击一个按钮来查看某个类别中的产品时,它应该会加载页面,但每次加载的不是目标操作,而是两个操作。因此,如果我单击Top Picks,它会加载Recommended,然后是Top Picks。如果我单击Recommended,它会加载New Releases,然后是最佳选择。就好像每个按钮同时被两件事触发。我不知道发生了什么。
这些按钮唯一拥有的东西(按钮看到所有)是一个指向flashDealCell的插座,所以我很困惑。
视频https://imgur.com/a/BqQD1sW
情节提要层次结构

可重用单元格

的视图层次结构注册操作的代码

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        if indexPath.section == 0 {
            //for category
            let cell = tableView.dequeueReusableCell(withIdentifier: "SeeAllProductsCell", for: indexPath) as! SeeAllProductsCell
            cell.selectionStyle = .none
            return cell
            
        } else if indexPath.section == 1 {
            
            //for featured products
            
            let cell = tableView.dequeueReusableCell(withIdentifier: "flashDealCell", for: indexPath) as! flashDealCell
            collectionview_featured = cell.collectionView_flashDeal
            //    collectionview_others.tag = indexPath.section
            collectionview_featured.delegate = self
            collectionview_featured.dataSource = self
            cell.label_header.text = "Top Picks"
            cell.button_seeAll.addTarget(self, action: #selector(SeeAllFeaturedProduct), for: .touchUpInside)
            cell.selectionStyle = .none
            if featuredData.count == 0 {
                cell.label_noProduct.isHidden = false
            }else
            {
                cell.label_noProduct.isHidden = true
            }
            cell.view_separator.isHidden = true
            return cell
       
           
        } else if indexPath.section == 2 {
            //for new arrivals
            let cell = tableView.dequeueReusableCell(withIdentifier: "flashDealCell", for: indexPath) as! flashDealCell
            collectionview_newArrival = cell.collectionView_flashDeal
       //     collectionview_others.tag = indexPath.section
            collectionview_newArrival.delegate = self
            collectionview_newArrival.dataSource = self
             cell.label_header.text = "New Releases"
            cell.button_seeAll.addTarget(self, action: #selector(SeeAllNewArrivalsProduct), for: .touchUpInside)
            cell.selectionStyle = .none
            
            if newArrivalsData.count == 0 {
                cell.label_noProduct.isHidden = false
            }else
            {
                cell.label_noProduct.isHidden = true
            }
            cell.view_separator.isHidden = false
           
            
            return cell
            
        }else{
            //for flash deals
            let cell = tableView.dequeueReusableCell(withIdentifier: "flashDealCell", for: indexPath) as! flashDealCell
            
            collectionview_flashDeals = cell.collectionView_flashDeal
            // collectionview_others.tag = indexPath.section
            collectionview_flashDeals.delegate = self
            collectionview_flashDeals.dataSource = self
            cell.label_header.text = "Recommended"//"On Sale"
            cell.button_seeAll.addTarget(self, action: #selector(SeeAllFlashDealsProduct), for: .touchUpInside)
            cell.selectionStyle = .none
            
            if flashDealsData.count == 0 {
                cell.label_noProduct.isHidden = false
                
            }else
            {
                cell.label_noProduct.isHidden = true
            }
            cell.view_separator.isHidden = false
            return cell
        }
    }

我的触发操作

@objc func SeeAllFlashDealsProduct()  {
        let vc = UIStoryboard.init(name: "Product", bundle: nil).instantiateViewController(withIdentifier: "FlashDealsVC") as! FlashDealsVC
        vc.headerText = "Recommended"//"On Sale"
        print("Clicked on Recommended")
        self.navigationController?.pushViewController(vc, animated: true)
        
    }
    @objc func SeeAllFeaturedProduct()  {
        //--
        let vc = UIStoryboard.init(name: "Product", bundle: nil).instantiateViewController(withIdentifier: "FlashDealsVC") as! FlashDealsVC
        vc.headerText = "Top Picks"
        print("Clicked on Top Picks")
        self.navigationController?.pushViewController(vc, animated: true)
    }
    @objc func SeeAllNewArrivalsProduct()  {
        let vc = UIStoryboard.init(name: "Product", bundle: nil).instantiateViewController(withIdentifier: "FlashDealsVC") as! FlashDealsVC
        vc.headerText = "New Releases"
        print("Clicked on New Releases")
        self.navigationController?.pushViewController(vc, animated: true)
        
    }
xmakbtuz

xmakbtuz1#

这福尔斯“在cellForRowAt中不应该做什么”的主题。
将目标/操作添加到UIButton***不会删除***任何现有目标/操作。
看看这个简单的例子-我们将创建一个按钮,并为三个不同的函数创建三次.addTarget

class BadTargetSetupVC: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        
        var cfg = UIButton.Configuration.filled()
        cfg.title = "Tap Me"
        let btn = UIButton(configuration: cfg)
        
        btn.translatesAutoresizingMaskIntoConstraints = false
        view.addSubview(btn)
        
        NSLayoutConstraint.activate([
            btn.centerXAnchor.constraint(equalTo: view.centerXAnchor),
            btn.centerYAnchor.constraint(equalTo: view.centerYAnchor),
        ])
        
        btn.addTarget(self, action: #selector(btnAction1(_:)), for: .touchUpInside)
        btn.addTarget(self, action: #selector(btnAction2(_:)), for: .touchUpInside)
        btn.addTarget(self, action: #selector(btnAction3(_:)), for: .touchUpInside)
    }
    
    @objc func btnAction1(_ sender: UIButton) {
        print("Action 1")
    }
    @objc func btnAction2(_ sender: UIButton) {
        print("Action 2")
    }
    @objc func btnAction3(_ sender: UIButton) {
        print("Action 3")
    }

}

如果运行该命令,每次点击按钮时,都会在调试控制台中看到以下内容:

Action 1
Action 2
Action 3

由于表格视图中的单元格是重用的,并且您要将第1、2和3部分的相同单元格类出队,因此每次重用单元格时,您*都会向按钮添加另一个目标/操作***。
这就是为什么你应该设计你的单元类来处理按钮点击
内部**,并使用closure(或协议/委托模式)来允许单元通知控制器按钮被点击。
然后,控制器可以根据单元的indexPath采取适当的操作。

flvlnr44

flvlnr442#

我在朋友的帮助下修好了

class flashDealCell : UITableViewCell{
    
    @IBOutlet weak var collectionView_flashDeal: UICollectionView!
    var index : Int!
    @IBOutlet weak var button_seeAll: UIButton!
    @IBOutlet weak var label_header: UILabel!
    @IBOutlet weak var label_noProduct: UILabel!
    @IBOutlet weak var view_separator: UIView!
    
    override func prepareForReuse() {
        self.button_seeAll.removeTarget(nil, action: nil, for: .touchUpInside)
        super.prepareForReuse()
    }
    
}

添加prepareForReuse有助于确保每个按钮只有一个操作,这不是最好的方法,但它现在很有效

相关问题