UIAction вызывает несколько раз при нажатии на UIButton в CollectionViewCell

Когда я нажимаю на кнопку, она срабатывает несколько раз.

Код файла 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.

2 ответа

Действия запускаются несколько раз, поскольку некоторые экземпляры повторно используютсяUICollectionView. Это означает, чтоdeleteButtonвозвращенных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
}

Одним из возможных решений является переопределениеprepareForReuse()вPhotoCell, какJohannупомянул.

preparaForReuse()is use to Выполняет любую очистку, необходимую для подготовки представления к повторному использованию.

Мы можем удалить все события с кнопки там!

      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
    }
Другие вопросы по тегам