2017-01-13 3 views
2

В моем проекте я настроил UITableView, ячейки которого привязаны к сегменту, который переводит пользователя в другой ViewController, где данные из ячейки отображаются в деталях. Однако не все ячейки должны выполнять сегмент (например, запись, представленная в ячейке, недействительна и не должна отображаться, поэтому переход к контроллеру детализации не требуется).Отображение UIAlertViewController в файле shouldPerformSegue

Для решения этой задачи я использую shouldPerformSegue метод в UIViewController в: (я предполагаю в следующем фрагменте, что вторая строка в таблице является тот, который не должен выполнять SEGUE)

override func shouldPerformSegue(withIdentifier identifier: String, sender: Any?) -> Bool { 
    guard let indexPath = tableView.indexPathForSelectedRow else { 
     return false 
    } 

    if indexPath.row == 1 { 
     let alert = UIAlertController(
      title: "Invalid record", 
      message: "This record is malformed, can't display the data.", 
      preferredStyle: .alert) 
     alert.addAction(UIAlertAction(title: "Okay :(", style: .default)) 
     present(alert, animated: true, completion: nil) 
     return false 
    } else { 
     return true 
    } 
} 

Это приводит к некоторым странное поведение: всякий раз, когда я нажимаю вторую строку, предупреждение отображается только через секунду или два, иногда даже через пять секунд после нажатия, и иногда оно вообще не отображается, пока я не выполню некоторые другие действия пользовательского интерфейса, такие как прокрутка вида таблицы или нажатие еще раз.

После нескольких проб и ошибок я нашел решение: предупреждение будет отображаться сразу после нажатия на «ошибочную» ячейке, когда я заставляю его в основной поток:

DispatchQueue.main.async { 
    present(alert, animated: true, completion: nil) 
} 

Это нелогичное для меня, поскольку метод prepareForSegue уже выполняется в основном потоке. Поэтому мой вопрос: откуда происходит неустойчивое поведение UIAlertController и нужно ли мне его отображать в основном потоке, или я делаю что-то неправильно?

+2

Это не значит, что 'shouldPerformSegue' находится не в главной очереди, а скорее в том, что эта функция задействована в процессе segue, поэтому неплохо представить представление другого представления на этом этапе. Используя асинхронную отправку, вы позволяете завершить текущий процесс segue (или прерваться в этом случае) до появления предупреждения. Это правильное решение вашей проблемы. – Paulw11

+1

Лично я проверял данные - перед выполнением segue - в методе tableView (_: didSelectRowAt :) delegate. –

+0

Да, я согласен с Томом, я проверил бы строку в файле didSelectRowAt и, если потребуется, вызовет executeSegueWithIdentifier только при необходимости. – Scriptable

ответ

1

Это не то, что shouldPerformSegue не находится в главной очереди, а скорее, что эта функция задействована в процессе segue, поэтому неплохо было бы представить другой вид на этом этапе.

С помощью async-диспетчеризации вы позволяете завершить текущий процесс segue (или прерваться в этом случае) перед представлением предупреждения.

Я думаю, что это разумное решение вашей проблемы.

Смежные вопросы