Как использовать shouldSelectItemAt в ожидании пользовательского ввода из предупреждения?

#ios #swift

#iOS #swift

Вопрос:

Я хочу отложить выбор элемента из представления коллекции до тех пор, пока пользователь не ответит на вопрос во всплывающем оповещении.

В этом сценарии — когда у меня запущен таймер, я хочу, чтобы всплывающее окно спрашивало, действительно ли они хотят переключиться на новый таймер (который они выбрали в представлении коллекции) и остановить таймер, который в данный момент запущен.

Однако — возврат происходит до того, как пользователь сможет ответить. Любая помощь была бы отличной.

 func collectionView(_ collectionView: UICollectionView, shouldSelectItemAt indexPath: IndexPath) -> Bool
    {
        var changeTimer: Bool = false

        if isTimerRunning {
            let alert = UIAlertController(title: "Switch Timers?", message: "Change timers now?", preferredStyle: UIAlertController.Style.alert)
            alert.addAction(UIAlertAction(title: "Yes", style: .default) { _ in                
                changeTimer = true
                // more code
            })

            alert.addAction(UIAlertAction(title: "Cancel", style: .default) { _ in
                changeTimer = false                
            })

            self.present(alert, animated: true, completion: nil)

        } else {
            changeTimer = true
            // more code
        }

        return changeTimer
    }
  

Ответ №1:

Это не может подождать с shouldSelectItemAt , но вы можете использовать вспомогательный метод, как показано ниже:

Прежде всего обновите свой shouldSelectItemAt метод, как показано ниже:

 func collectionView(_ collectionView: UICollectionView, shouldSelectItemAt indexPath: IndexPath) -> Bool {

    if isTimerRunning {
        showConfirmationPopUp(indexPath: indexPath)
        return false
    } else {
        return true
    }
}
  

затем добавьте showConfirmationPopUp метод:

 func showConfirmationPopUp(indexPath: IndexPath) {

    let alert = UIAlertController(title: "Switch Timers?", message: "Change timers now?", preferredStyle: UIAlertController.Style.alert)
    alert.addAction(UIAlertAction(title: "Yes", style: .default) { _ in
        // more code
        self.myCollectionView.delegate?.collectionView!(self.myCollectionView, didSelectItemAt: indexPath)
    })

    alert.addAction(UIAlertAction(title: "Cancel", style: .default) { _ in

    })

    self.present(alert, animated: true, completion: nil)
}
  

Теперь, как только пользователь нажмет на Yes опцию, которую вы didSelectItemAt вызовете.

Но вы можете игнорировать

 self.myCollectionView.delegate?.collectionView!(self.myCollectionView, didSelectItemAt: indexPath)
  

Если вы не хотите вызывать, didSelectItemAt и вы можете внести свои изменения для этой выбранной ячейки в Yes обработчике действий напрямую, как у вас есть indexPath в вашем showConfirmationPopUp методе.

Ответ №2:

Вы можете полностью установить для выбора CollectionView значение none и внутри

 var currentSelected:Int?

func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) -> Bool

  // show alert and in success part reload the collectionView  

        let alert = UIAlertController(title: "Switch Timers?", message: "Change timers now?", preferredStyle: UIAlertController.Style.alert)
        alert.addAction(UIAlertAction(title: "Yes", style: .default) { _ in                

            self.currentSelected =  indexPath.item

            self.collectionView.reloadData()
        })

        alert.addAction(UIAlertAction(title: "Cancel", style: .default) { _ in 
        })

        self.present(alert, animated: true, completion: nil)

}
  

Затем внутри cellForItemAt

  if indexPath.item == currentSelected {
    // color it
 else {
    // not selected 
 }