在 CollectionViewCell swift 5

问题描述 投票:0回答:2

当我点击按钮时,它会触发多次。

CollectionViewCell文件代码

class PhotoCell: UICollectionViewCell {
    @IBOutlet weak var deleteButton: UIButton!
}

ViewController - cellforItemAt 方法实现

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "PhotoCell", for: indexPath) as? PhotoCell else { return UICollectionViewCell() }

        let action = UIAction { _ in
            print("Delete button tapped!!!", indexPath.row)
        }

        cell.deleteButton.addAction(action, for: .touchUpInside)

        return cell
    }

如果我配置 UIButton addTarget 那么它工作正常但我不确定为什么它不能与 addAction 一起工作。谢谢!

swift uibutton swift5 ios14 uiaction
2个回答
1
投票

动作被多次触发,因为

PhotoCell
的一些实例被
UICollectionView
重用。这意味着
deleteButton
返回的
PhotoCell
dequeueReusableCell()
可能已经添加了动作,并且最终将拥有针对相同事件的多个动作。

一个可能的解决方案是覆盖

prepareForReuse()
中的
PhotoCell
并删除那里的动作。

class PhotoCell: UICollectionViewCell {
    @IBOutlet weak var deleteButton: UIButton!
    var actions: [(UIAction, UIControl.Event)] = []

    func addAction(_ action: UIAction, for event: UIControl.Event) {
        self.actions.append((action, event))
        self.deleteButton.addAction(action, for: event)
    }

    override func prepareForReuse() {
        super.prepareForReuse()
        for tuple in self.actions {
            self.deleteButton.removeAction(tuple.0, for: tuple.1)
        }
        self.actions = []
    }
}

使用上述代码时

addAction
需要在
cell
上调用,而不是在函数
cell.deleteButton
中调用
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath)

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "PhotoCell", for: indexPath) as? PhotoCell else { return UICollectionViewCell() }

    let action = UIAction { _ in
        print("Delete button tapped!!!", indexPath.row)
    }
    cell.addAction(action, for: .touchUpInside)

    return cell
}

0
投票

一个可能的解决方案是在

prepareForReuse()
中覆盖
PhotoCell
,如
Johann
所述。

preparaForReuse()
用于执行任何必要的清理 准备视图以供再次使用。

我们可以从那里的按钮中删除所有事件!

class PhotoCell: UICollectionViewCell {
    @IBOutlet weak var deleteButton: UIButton!

     override func prepareForReuse() {
        super.prepareForReuse()
        self.deleteButton.removeTarget(nil, action: nil, for: .allEvents)
    }

}

像往常一样在

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath)
中添加动作。

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "PhotoCell", for: indexPath) as? PhotoCell else { return UICollectionViewCell() }
        let action = UIAction { _ in
            print("Delete button tapped!!!", indexPath.row)
        }
        cell.deleteButton.addAction(action, for: .touchUpInside)
        return cell
    }
© www.soinside.com 2019 - 2024. All rights reserved.