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
}