Acabo de comenzar a usar Xcode 4.5 y recibí este error en la consola:
Advertencia: ¡Intente presentar <finishViewController: 0x1e56e0a0> en <ViewController: 0x1ec3e000> cuya vista no está en la jerarquía de la ventana!
La vista aún se presenta y todo en la aplicación funciona bien. ¿Es esto algo nuevo en iOS 6?
Este es el código que estoy usando para cambiar entre vistas:
UIStoryboard *storyboard = self.storyboard;
finishViewController *finished =
[storyboard instantiateViewControllerWithIdentifier:@"finishViewController"];
[self presentViewController:finished animated:NO completion:NULL];
presentViewController:animated:completion
a un controlador de navegación. ¿Estás haciendo esto en el delegado de la aplicación?Respuestas:
¿Desde dónde llamas a este método? Tuve un problema en el que intentaba presentar un controlador de vista modal dentro del
viewDidLoad
método. La solución para mí fue trasladar esta llamada alviewDidAppear:
método.Mi suposición es que la vista del controlador de vista no está en la jerarquía de vista de la ventana en el punto en que se ha cargado (cuando
viewDidLoad
se envía el mensaje), pero está en la jerarquía de la ventana después de que se haya presentado (cuandoviewDidAppear:
se envía el mensaje) .Precaución
Si usted hace una llamada a
presentViewController:animated:completion:
laviewDidAppear:
que puede ejecutar en un problema por el que siempre se presenta el controlador de vista modal siempre que aparezca la opinión de la vista controlador (lo cual tiene sentido!) Y por lo que el controlador de vista modal que se presenta nunca desaparecerá .. .Tal vez este no sea el mejor lugar para presentar el controlador de vista modal, o tal vez sea necesario mantener algún estado adicional que permita al controlador de vista de presentación decidir si debe o no presentar el controlador de vista modal de inmediato.
fuente
Otra posible causa:
Tuve este problema cuando accidentalmente presentaba el mismo controlador de vista dos veces. (Una vez con lo
performSegueWithIdentifer:sender:
que se llamó cuando se presionó el botón, y una segunda vez con un segmento conectado directamente al botón).Efectivamente, dos segues se dispararon al mismo tiempo, y obtuve el error:
Attempt to present X on Y whose view is not in the window hierarchy!
fuente
present(viewController, animated: true, completion: nil)
dentro de un bucle.viewWillLayoutSubviews
yviewDidLayoutSubviews
(iOS 5.0+) se pueden usar para este propósito. Se llaman antes que viewDidAppear.fuente
Para mostrar cualquier subvista a la vista principal, utilice el siguiente código
Para descartar cualquier subvista de la vista principal, utilice el siguiente código
fuente
También me encontré con este problema cuando intenté presentar un
UIViewController
inviewDidLoad
. La respuesta de James Bedford funcionó, pero mi aplicación mostró el fondo primero durante 1 o 2 segundos.Después de investigar un poco, he encontrado una manera de resolver esto usando el
addChildViewController
.fuente
Probablemente, como yo, tienes una raíz incorrecta
viewController
Quiero mostrar un
ViewController
en unnon-UIViewController
contexto,Entonces no puedo usar ese código:
Entonces, obtengo un UIViewController:
Por alguna razón (error lógico), el
rootViewController
es algo diferente de lo esperado (normalUIViewController
). Luego corrijo el error, reemplazandorootViewController
con aUINavigationController
, y el problema se ha ido.fuente
TL; DR Solo puede tener 1 rootViewController y es el presentado más recientemente. Por lo tanto, no intente que un viewcontroller presente otro viewcontroller cuando ya se haya presentado uno que no se ha descartado.
Después de hacer algunas de mis propias pruebas, he llegado a una conclusión.
Si tiene un rootViewController que desea presentar todo, entonces puede encontrarse con este problema.
Aquí está mi código rootController (abrir es mi acceso directo para presentar un viewcontroller desde la raíz).
Si llamo a abrir dos veces seguidas (independientemente del tiempo transcurrido), esto funcionará bien en la primera apertura, pero NO en la segunda apertura. El segundo intento de apertura dará como resultado el error anterior.
Sin embargo, si cierro la vista presentada más recientemente y llamo a abrir, funciona bien cuando llamo a abrir nuevamente (en otro controlador de vista).
Lo que he concluido es que el rootViewController de solo MOST-RECENT-CALL está en la vista Jerarquía (incluso si no lo descartó o eliminó una vista). Traté de jugar con todas las llamadas del cargador (viewDidLoad, viewDidAppear y haciendo llamadas de despacho retrasado) y descubrí que la única forma en que puedo hacer que funcione es SOLO llamando al presente desde el controlador de la vista superior.
fuente
wait
wait
decide
push screen to front
y es IMPOSIBLE es IOS ????Mi problema fue que estaba realizando el segue en
UIApplicationDelegate
'sdidFinishLaunchingWithOptions
método antes de llamarmakeKeyAndVisible()
a la ventana.fuente
En mi situación, no pude poner el mío en una anulación de clase. Entonces, esto es lo que obtuve:
fuente
Yo tuve el mismo problema. Tuve que incrustar un controlador de navegación y presentar el controlador a través de él. A continuación se muestra el código de muestra.
fuente
Si tiene un objeto AVPlayer con video reproducido, primero debe pausar el video.
fuente
Tuve el mismo problema. El problema era que el performanceSegueWithIdentifier fue activado por una notificación, tan pronto como puse la notificación en el hilo principal, el mensaje de advertencia desapareció.
fuente
Está funcionando bien, prueba esto. Enlace
fuente
En caso de que ayude a alguien, mi problema fue extremadamente tonto. Totalmente mi culpa, por supuesto. Una notificación activaba un método que estaba llamando al modal. Pero no estaba eliminando la notificación correctamente, por lo que en algún momento, tendría más de una notificación, por lo que el modal se llamaría varias veces. Por supuesto, después de llamar al modal una vez, el controlador de vista que lo llama ya no está en la jerarquía de vistas, es por eso que vemos este problema. Mi situación también causó muchos otros problemas, como era de esperar.
Para resumir, haga lo que esté haciendo, asegúrese de que el modal no se llame más de una vez .
fuente
Terminé con un código que finalmente me funciona (Swift), teniendo en cuenta que desea mostrar algunos
viewController
desde prácticamente cualquier lugar. Este código obviamente se bloqueará cuando no haya rootViewController disponible, ese es el final abierto. Tampoco incluye el cambio generalmente requerido al subproceso de interfaz de usuario usandofuente
Este tipo de advertencia puede significar que usted está tratando de nuevo presente
View Controller
a travésNavigation Controller
mientras que estoNavigation Controller
está presentando otraView Controller
. Para solucionarlo, debe descartar el actual presentadoView Controller
al principio y al finalizar presentar el nuevo. Otra causa de la advertencia puede ser intentar presentarView Controller
en un hilo distinto demain
.fuente
Tuve un problema similar en Swift 4.2 pero mi vista no se presentó desde el ciclo de vista. Descubrí que tenía múltiples segue para ser presentado al mismo tiempo. Entonces usé dispatchAsyncAfter.
fuente
Lo arreglé moviendo la
start()
función dentro deldismiss
bloque de finalización:Inicio contiene dos llamadas a
self.present()
una para un UINavigationController y otra para aUIImagePickerController
.Eso me lo arregló.
fuente
También puede obtener esta advertencia cuando realice una segue desde un controlador de vista que está incrustado en un contenedor. La solución correcta es usar segue del padre del contenedor, no del controlador de vista del contenedor.
fuente
Tiene que escribir debajo de la línea.
en vez de
en UIViewController
fuente
Con Swift 3 ...
Otra posible causa de esto, que me sucedió, fue pasar de una tabla ViewCell a otra ViewController en el Storyboard. También lo usé
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {}
cuando se hizo clic en la celda.Solucioné este problema al pasar de ViewController a ViewController.
fuente
Tuve este problema, y la causa raíz fue suscribirse a un controlador de clic de botón (TouchUpInside) varias veces.
Se estaba suscribiendo en ViewWillAppear, que se llamaba varias veces desde que agregamos la navegación para ir a otro controlador y luego volver a ella.
fuente
Me sucedió que la segue en el guión gráfico estaba rota . Eliminar el segue (y crear exactamente el mismo segue nuevamente) resolvió el problema.
fuente
Con su ventana principal, es probable que siempre haya momentos con transiciones que sean incompatibles con la presentación de una alerta. Para permitir la presentación de alertas en cualquier momento en el ciclo de vida de su aplicación, debe tener una ventana separada para hacer el trabajo.
Uso básico que, por diseño, siempre tendrá éxito:
fuente
Lamentablemente, la solución aceptada no funcionó para mi caso. Estaba tratando de navegar a un nuevo controlador de vista justo después de desconectarme de otro controlador de vista.
Encontré una solución usando una bandera para indicar qué desenvolvimiento se llamó.
Luego presente el VC deseado con
present(_ viewControllerToPresent: UIViewController)
Básicamente, el código anterior me permitirá capturar la desconexión del inicio de sesión / Registrarse VC y navegar al panel de control, o capturar la acción de desconexión de olvidar la contraseña VC y navegar a la página de inicio de sesión.
fuente
Solucioné este error al almacenar la mayoría del viewcontroller superior en constante que se encuentra dentro del ciclo sobre rootViewController:
fuente
Encontré que este error llegó después de actualizar Xcode, creo que Swift 5 . El problema estaba ocurriendo cuando programáticamente inicié un segue directamente después de desenrollar un controlador de vista.
La solución llegó mientras se solucionaba un error relacionado, que era que el usuario ahora podía desenvolverse segues deslizando la página hacia abajo. Esto rompió la lógica de mi programa.
Se solucionó cambiando el modo Presentación en todos los controladores de vista de Automático a Pantalla completa .
Puede hacerlo en el panel de atributos en el generador de interfaces. O vea esta respuesta para saber cómo hacerlo programáticamente.
fuente
También tuve este problema, pero no tenía nada que ver con el momento. Estaba usando un singleton para manejar escenas, y lo configuré como presentador. En otras palabras, "Self" no estaba conectado a nada. Acabo de hacer su "escena" interior el nuevo presentador y listo, funcionó. (Voila pierde su toque después de que aprendes su significado, je).
Entonces, sí, no se trata de "encontrar mágicamente el camino correcto", se trata de entender dónde se encuentra su código y qué está haciendo. Estoy feliz de que Apple haya dado un mensaje de advertencia tan simple en inglés, incluso con emoción. ¡Felicitaciones al desarrollador de Apple que hizo eso!
fuente
Si otras soluciones no se ven bien por alguna razón, aún puede usar este viejo
workaround
anticipo de presentar con el retraso de 0, así:Si bien no he visto ninguna garantía documentada de que su VC estaría en la jerarquía de vistas en el momento en que el bloque de despacho está programado para ejecutarse, he observado que funcionaría bien.
Usar una demora de, por ejemplo, 0.2 segundos también es una opción. Y lo mejor: de esta manera no necesita meterse con la variable booleana en
viewDidAppear:
fuente
Esto funciona para presentar cualquier controlador de vista, si tiene un controlador de navegación disponible. self.navigationController? .present (MyViewController, animado: verdadero, finalización: nulo) Además, puedo presentar alertas y el controlador de correo también.
fuente