PerformSegueWithIdentifier очень медленный, когда segue является модальным
У меня есть простой вид таблицы, где я обрабатываю действие select в представлении таблицы. Это действие следует за шагом.
Если segue является push
segue, следующее представление отображается немедленно.
Если segue является modal
segue, следующий вид:
- требуется около 6 секунд для отображения
- показывает сразу, если я снова нажимаю (второй раз)
Я попытался оглянуться на некоторые идеи, но ни одна из них не применима к моей ситуации. В частности:
- Я выполняю segue в основном потоке пользовательского интерфейса.
- Мое мнение очень просто (поэтому нет проблем в
viewDidLoad
). Плюс тот факт, что он отображается почти мгновенно, когда segue push
указывает, что нет проблем с загрузкой целевого представления
- Я пробовал передать
nil
в sender
; такой же эффект.
Есть ли у кого-нибудь идеи по этому поводу?
Ответы
Ответ 1
Поверьте мне и попробуйте это. Я несколько раз сталкивался с этой проблемой.
В Swift 2:
dispatch_async(dispatch_get_main_queue(),{
self.performSegue(withIdentifier:mysegueIdentifier,sender: self)
})
или для Swift 3:
DispatchQueue.main.async {
self.performSegue(withIdentifier: mysegueIdentifier,sender: self)
}
Как обсуждалось здесь и здесь.
Ответ 2
Кажется (мне...), что эта проблема возникает только тогда, когда ячейка selectionType
не .none
.
Вы можете изменить его на любой другой вариант (в раскадровке Attribute inspector
, установите поле Selection
), и он будет работать нормально (работает для меня...).
Недостатком является то, что он испортил пользовательский интерфейс ячейки.
Вы можете вызвать segue в блоке DispatchQueue.main.async{}
в функции делегата didSelect
от UITableViewDelegate
, как упоминалось ранее.
Я использовал первое решение и добавил его в ячейку -
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(false, animated: false)
}
Это сделает ячейку "выделенной" на кране, но она вернется к своему обычному пользовательскому интерфейсу сразу, и это отлично для меня...
Ответ 3
Кажется, что различные ситуации, когда выполнение segue не будет работать должным образом. Например, если вы вызываете performSegue
из обработчика события разматывания, вы столкнетесь с различными проблемами, даже если вы находитесь в основном потоке. В моем текущем проекте я вызываю performSegue
из метода didSelectRowAt
представления таблицы. Это один из самых основных сегментов и, конечно же, я нахожусь в основном потоке, но я видел точные симптомы, описанные ОП.
Я не знаю, почему это происходит в некоторых случаях, а не в других, но я обнаружил, что отсрочка вызова performSegue
с помощью async
устраняет любые потенциальные проблемы. Раньше это выглядело как хак и заставляло меня нервничать, но на данный момент у меня есть несколько зрелых проектов, использующих этот подход, и теперь это похоже на "правильный" способ сделать ручной сеанс.
Вот версия кода Swift 3 (см. другие сообщения для версий Swift 2 и Obj-C):
DispatchQueue.main.async {
self.performSegue(withIdentifier: "theIdentifier", sender: theSender)
}
Ответ 4
Принятое решение сработало для меня. Код обновлен для Swift 2.0 ниже:
dispatch_async(dispatch_get_main_queue(),{
self.performSegueWithIdentifier(mysegueIdentifier, sender:self)
})
Ответ 5
Надеемся, что эта помощь может создать программно-модальный переход, подобный этому в Swift:
let myStoryboard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let modalViewController = myStoryboard.instantiateViewControllerWithIdentifier("myModalViewController") as! myModalViewController
modalViewController.modalTransitionStyle = UIModalTransitionStyle.CoverVertical
let navController = UINavigationController(rootViewController: accountManager)
dispatch_async(dispatch_get_main_queue(),{
self.presentViewController(navController, animated: true, completion: nil)
})
Ответ 6
Для разработчиков, организующих свой код с помощью подкласса, я пришел к довольно простому решению, которое хотел бы поделиться (Swift 4):
import UIKit
class ABCViewController: UIViewController {
// ... Other useful methods like overriding deinit and didReceiveMemoryWarning
// Performs a segue on the main thread to ensure it will
// transition once a UI-slot is available
func performSegueOnMainThread(with identifier: String, sender: Any?) {
DispatchQueue.main.async {
self.performSegue(with: identifier, sender: sender)
}
}
}
Затем просто назовите его из своей реализации:
myViewController.performSegueOnMainThread(with: "ShowDetailsSegue", sender: self)
Ответ 7
Для меня это было то, что у меня было слишком много "чистых" цветных представлений в моем следующем виде, поэтому, когда переход был анимированным, казалось, что он задерживается из-за этого. Я просмотрел иерархию пользовательского интерфейса контроллера представления в поисках чистых цветов, заменил их сплошным черным или белым и убедился, что альфа равна 1 (если не нужно было иначе). Моя задержка теперь прошла, и мое модальное представление гладко.
Ответ 8
Я попытался исправить это несколько способов, в том числе переместить его в основной поток выше. Это сработало для меня:
В раскадровке выберите рассматриваемое представление таблицы (выберите его в контуре документа, чтобы убедиться, что у вас есть правильная вещь. Затем в инспекторе атрибутов вы сможете увидеть атрибуты для представления таблицы, а также содержащего scrollview под ним (все представления таблиц основаны на просмотре прокрутки). В этой глупой маленькой коробке есть "задержек содержания". Снимите флажок. Также есть "разрешает отменить касания", которые, я думаю, вы хотите сделать уверен, также не отмечен, так как я думаю, что двойные касания были беспорядочными.