performSegueWithIdentifier muy lento cuando segue es modal

Tengo una vista de tabla simple donde manejo la acción de selección en la vista de tabla. Esta acción sigue un segue.

Si el segue es un segue de push , la siguiente vista se muestra inmediatamente. Si el cambio es un cambio modal , la próxima vista ya sea:

  • tarda 6 segundos más o menos para mostrar
  • muestra inmediatamente si toco nuevamente (segundo toque)

Traté de buscar algunas ideas, pero ninguna parece aplicable a mi situación. En particular:

  • Estoy realizando el cambio en el hilo principal de la interfaz de usuario
  • Mi vista es muy simple (por lo que no hay ningún problema en viewDidLoad ). Además, el hecho de que aparece casi instantáneamente cuando el segue es push indica que no hay ningún problema al cargar la vista de destino
  • Traté de pasarle nil al sender ; mismo efecto.

¿Alguien tiene alguna idea sobre esto?

Confía en mí y prueba esto. Me he encontrado con este problema algunas veces.

En Swift 2:

 dispatch_async(dispatch_get_main_queue(),{ self.performSegue(withIdentifier:mysegueIdentifier,sender: self) }) 

o para Swift 3:

 DispatchQueue.main.async { self.performSegue(withIdentifier: mysegueIdentifier,sender: self) } 

Como se discutió aquí y aquí .

Me parece (a mí …) que este problema ocurre solo cuando el Cell selectionType no es .none .

Puede cambiarlo a cualquier otra opción (en el Attribute inspector del guión gráfico, establecer el campo Selection ) y funcionará bien (trabajando para mí …). La desventaja es que arruina la interfaz de usuario de la célula.

Puede llamar a la segue en el bloque DispatchQueue.main.async{} en la función delegar UITableViewDelegate de UITableViewDelegate como mencionan anteriormente las personas.

Usé la primera solución y la agregué a la misma celda:

 override func setSelected(_ selected: Bool, animated: Bool) { super.setSelected(false, animated: false) } 

Esto hará que la celda se “ilumine” en el grifo, pero volverá a su interfaz de usuario habitual inmediatamente y me parece bien …

Parece haber varias situaciones cuando realizar un segue no funcionará correctamente. Por ejemplo, si llama a performSegue desde el controlador de acción de un segue de desenrollado, se encontrará con varios problemas, aunque se encuentre en el hilo principal. En mi proyecto actual, estoy llamando a performSegue desde el método didSelectRowAt de una vista de tabla. Este es uno de los pasos más básicos que hay y, por supuesto, estoy en el hilo principal, sin embargo, estaba viendo los síntomas exactos que describió el OP.

No sé por qué sucede esto en algunos casos y no en otros, pero he encontrado que aplazar la llamada a performSegue usando async corrige cualquier posible problema. Esto solía parecer un truco y me ponía nervioso, pero en este punto tengo varios proyectos maduros que usan este enfoque y ahora parece ser la forma “correcta” de hacer una transición manual.

Aquí está la versión Swift 3 del código (vea las otras publicaciones para las versiones Swift 2 y Obj-C):

 DispatchQueue.main.async { self.performSegue(withIdentifier: "theIdentifier", sender: theSender) } 

La solución aceptada funcionó para mí. Código actualizado para Swift 2.0 a continuación:

 dispatch_async(dispatch_get_main_queue(),{ self.performSegueWithIdentifier(mysegueIdentifier, sender:self) }) 

Espero que esto ayude a crear una transición modal programática como esta en 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) }) 

Para los desarrolladores que organizan su código a través de subclases, he llegado a una solución bastante simple que me gustaría compartir (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) } } } 

Entonces, simplemente llámalo desde tu implementación:

 myViewController.performSegueOnMainThread(with: "ShowDetailsSegue", sender: self) 

Traté de solucionar esto de múltiples maneras, incluyendo moverlo al hilo principal anterior. Esto funcionó para mí:

En el guión gráfico, seleccione la vista de tabla en cuestión (selecciónela en el esquema del documento para asegurarse de que tiene lo correcto. Luego, en el inspector de atributos, podrá ver los atributos de la vista de tabla, así como la vista de desplazamiento que los contiene (todas las vistas de tabla se basan en la vista de desplazamiento). Hay una pequeña caja estúpida llamada “demora toques de contenido”. Desmárcala. También hay una “que permite toques cancelables” que me imagino que quieres asegurarte de que está desactivada también, como creo que los toques dobles estaban estropeando el mío.