He leído muchos mensajes acerca de las personas que tienen problemas con viewWillAppear
cuando no se crea la jerarquía de vista simplemente correcto. Mi problema es que no puedo entender qué significa eso.
Si creo un RootViewController
y llamo addSubView
a ese controlador, esperaría que las vistas agregadas estén conectadas para viewWillAppear
eventos.
¿Alguien tiene un ejemplo de una jerarquía de vista programática compleja que reciba viewWillAppear
eventos con éxito en todos los niveles?
Estado de los documentos de Apple:
Advertencia: Si la vista que pertenece a un controlador de vista se agrega directamente a una jerarquía de vista, el controlador de vista no recibirá este mensaje. Si inserta o agrega una vista a la jerarquía de vistas y tiene un controlador de vista, debe enviar este mensaje directamente al controlador de vista asociado. Si no se envía el controlador de vista, este mensaje evitará que se muestre cualquier animación asociada.
El problema es que no describen cómo hacer esto. ¿Qué significa "directamente"? ¿Cómo se agrega "indirectamente" una vista?
Soy bastante nuevo en Cocoa y iPhone, por lo que sería bueno si hubiera ejemplos útiles de Apple además de la basura básica de Hello World.
fuente
Respuestas:
Si utiliza un controlador de navegación y establece su delegado, los métodos de vista {Will, Did} {Appear, Disappear} no se invocan.
En su lugar, debe usar los métodos delegados del controlador de navegación:
fuente
Me he encontrado con el mismo problema. Simplemente envíe un
viewWillAppear
mensaje a su controlador de vista antes de agregarlo como una subvista. (Hay un parámetro BOOL que le dice al controlador de vista si se está animando a aparecer o no).Mire RootViewController.m en el ejemplo de Metronome.
(De hecho, los proyectos de ejemplo de Apple me parecieron geniales. Hay MUCHO más que HelloWorld;)
fuente
[scrollView addSubview:controller.view];
. Agregué la línea[controller viewWillAppear:NO];
después y ¡voilá! Trabajado como un encanto.Finalmente encontré una solución para esto ¡QUE FUNCIONA!
UINavigationControllerDelegate
Creo que la esencia es configurar el delegado de su control de navegación en el controlador de vista en el que se encuentra, e implementarlo
UINavigationControllerDelegate
y sus dos métodos. ¡Brillante! ¡Estoy tan emocionado de que finalmente encontré una solución!fuente
Solo tuve el mismo problema. En mi aplicación tengo 2 controladores de navegación y presionar el mismo controlador de vista en cada uno de ellos funcionó en un caso y no en el otro. Quiero decir que al presionar exactamente el mismo controlador de vista en el primero
UINavigationController
,viewWillAppear
se llamó pero no cuando se presionó en el segundo controlador de navegación.Entonces me encontré con esta publicación UINavigationController debería llamar a los métodos viewWillAppear / viewWillDisappear
Y me di cuenta de que mi segundo controlador de navegación se redefinió
viewWillAppear
. Analizar el código mostró que no estaba llamando¡Lo agregué y funcionó!
La documentación dice:
fuente
He estado usando un controlador de navegación. Cuando quiero descender a otro nivel de datos o mostrar mi vista personalizada, uso lo siguiente:
Cuando hago esto, consigo que la
viewWillAppear
función se active. Supongo que esto califica como "indirecto" porque no estoy llamando aladdSubView
método real yo mismo. No sé si esto es 100% aplicable a su aplicación, ya que no puedo decir si está usando un controlador de navegación, pero tal vez proporcione una pista.fuente
Gracias iOS 13.
Los créditos van a Arek Holko . Realmente me salvó el día.
fuente
En primer lugar, la barra de pestañas debe estar en el nivel raíz, es decir, agregada a la ventana, como se indica en la documentación de Apple. Esta es la clave para un comportamiento correcto.
En segundo lugar, puede usar
UITabBarDelegate
/UINavigationBarDelegate
para reenviar las notificaciones manualmente, pero descubrí que para que toda la jerarquía de llamadas de vista funcione correctamente, todo lo que tenía que hacer era llamar manualmentey
.. solo UNA VEZ antes de configurar los controladores de vista en el controlador respectivo (justo después de la asignación). A partir de ese momento, llamó correctamente a estos métodos en sus controladores de vista secundarios.
Mi jerarquía es así:
El simple hecho de llamar a los métodos mencionados en la pestaña / controlador de navegación por primera vez aseguró que TODOS los eventos se reenviaron correctamente. Me impidió tener que llamarlos manualmente desde
UINavigationBarDelegate
/UITabBarControllerDelegate
métodos.Nota al margen: Curiosamente, cuando no funcionó, el método privado
.. que puede ver en la pila de llamadas en una implementación en funcionamiento, normalmente llama al
viewWill/Did..
métodos, pero no lo hizo hasta que realicé lo anterior (a pesar de que fue llamado).Sin embargo, creo que es MUY importante que
UITabBarController
esté al nivel de la ventana y los documentos parecen respaldar esto.Espero que haya sido claro (ish), feliz de responder más preguntas.
fuente
Como no se acepta respuesta y la gente (como yo) aterriza aquí, doy mi variación. Aunque no estoy seguro de que ese fuera el problema original. Cuando el controlador de navegación se agrega como una subvista a otra vista, debe llamar a los métodos viewWillAppear / Dissappear, etc. usted mismo de esta manera:
Solo para completar el ejemplo. Este código aparece en mi ViewController donde creé y agregué el controlador de navegación a una vista que coloqué en la vista.
el .h se ve así
En el archivo nib tengo la vista y debajo de esta vista tengo una etiqueta, una imagen y el contenedor (otra vista) donde coloco el controlador. Así es como se ve. Tuve que revolver algunas cosas ya que esto era trabajo para un cliente.
fuente
Las vistas se agregan "directamente" llamando
[view addSubview:subview]
. Las vistas se agregan "indirectamente" mediante métodos como barras de pestañas o barras de navegación que intercambian subvistas.Cada vez que llame
[view addSubview:subviewController.view]
, debe llamar[subviewController viewWillAppear:NO]
(o SÍ, según sea su caso).Tuve este problema cuando implementé mi propio sistema de administración de vista raíz personalizado para una subpantalla en un juego. Agregar manualmente la llamada a viewWillAppear solucionó mi problema.
fuente
La forma correcta de hacer esto es usando la API de contención UIViewController.
fuente
viewWillAppear:
posible que aún no se llameUtilizo este código para controladores de vista push y pop:
empujar:
popular:
.. y funciona bien para mí.
fuente
Un error muy común es el siguiente. Tiene un punto de vista,
UIView* a
y otro,UIView* b
. Agrega b a a como una subvista. Si intenta llamar a viewWillAppear en b, nunca se disparará, porque es una subvista de unfuente
iOS 13 mordió mi aplicación en el trasero aquí. Si ha notado un cambio de comportamiento a partir de iOS 13, simplemente configure lo siguiente antes de presionarlo:
Es posible que también deba configurarlo en su .storyboard en el inspector de atributos (configure Presentación en Pantalla completa).
Esto hará que su aplicación se comporte como lo hacía en versiones anteriores de iOS.
fuente
No estoy 100% seguro de esto, pero creo que agregar una vista a la jerarquía de vista significa directamente llamar
-addSubview:
a la vista del controlador de vista (por ejemplo,[viewController.view addSubview:anotherViewController.view]
) en lugar de empujar un nuevo controlador de vista a la pila del controlador de navegación.fuente
Creo que agregar una subvista no significa necesariamente que la vista aparecerá, por lo que no hay una llamada automática al método de la clase que lo hará.
fuente
Creo que lo que quieren decir "directamente" es conectar las cosas de la misma manera que lo hace la plantilla "Aplicación de navegación" de xcode, que establece el UINavigationController como la única subvista de la UIWindow de la aplicación.
El uso de esa plantilla es la única forma en que he podido obtener los métodos Will / Did / Appear / Disappear llamados en el objeto ViewControllers al presionar / hacer estallar esos controladores en el UINavigationController. Ninguna de las otras soluciones en las respuestas aquí funcionó para mí, incluida la implementación en RootController y pasarlas al NavigationController (secundario). Esas funciones (aparecerán / aparecerán / desaparecerán) solo se llamaron en mi RootController al mostrar / ocultar los VC de nivel superior, mi "login" y los VC de navegación, no los sub-VC en el controlador de navegación, por lo que no tuve la oportunidad de "pasarlos" al Nav VC.
Terminé usando la funcionalidad de delegado de UINavigationController para buscar las transiciones particulares que requerían funcionalidad de seguimiento en mi aplicación, y eso funciona, pero requiere un poco más de trabajo para conseguir que tanto la funcionalidad de desaparecer como la de aparecer "simulen".
También es una cuestión de principios hacer que funcione después de golpearme la cabeza contra este problema durante horas hoy. Cualquier fragmento de código que funcione utilizando un RootController personalizado y un VC de navegación secundario sería muy apreciado.
fuente
En caso de que esto ayude a alguien. Tuve un problema similar donde mi
ViewWillAppear
no está disparando en unUITableViewController
. Después de jugar mucho, me di cuenta de que el problema era que elUINavigationController
que está controlando miUITableView
no está en la vista raíz. Una vez que solucione eso, ahora funciona como un campeón.fuente
Yo mismo tuve este problema y me llevó 3 horas completas (2 de las cuales busqué en Google) solucionarlo.
Lo que resultó ser de ayuda fue simplemente eliminar la aplicación del dispositivo / simulador, limpiar y luego ejecutar nuevamente .
Espero que ayude
fuente
Establezca el delegado en el controlador de vista raíz.
fuente
Para Swift. Primero cree el protocolo para llamar a lo que quería llamar en viewWillAppear
Segundo, crea la clase
}
En tercer lugar, haga que la instancia de ForceUpdateOnViewAppear sea el miembro de la clase adecuada que tenga acceso al controlador de navegación y exista mientras exista el controlador de navegación. Puede ser, por ejemplo, el controlador de vista raíz del controlador de navegación o la clase que lo crea o lo presenta. Luego asigne la instancia de ForceUpdateOnViewAppear a la propiedad de delegado del controlador de navegación lo antes posible.
fuente
En mi caso, el problema fue con la animación de transición personalizada. Cuando se establece
modalPresentationStyle = .custom
viewWillAppear
no se llamaen la clase de animación de transición personalizada se necesitan métodos de llamada:
beginAppearanceTransition
yendAppearanceTransition
fuente
En mi caso, eso fue solo un error extraño en el emulador de ios 12.1. Desapareció después de lanzarse en un dispositivo real.
fuente
He creado una clase que resuelve este problema. Simplemente configúrelo como un delegado de su controlador de navegación e implemente uno o dos métodos simples en su controlador de vista, que se llamarán cuando la vista esté a punto de mostrarse o se haya mostrado a través de NavigationController
Aquí está el GIST que muestra el código
fuente
ViewWillAppear es un método de anulación de la clase UIViewController, por lo que agregar un subView no llamará a viewWillAppear, pero cuando presente, presione, muestre, muestre, establezca o haga popToRootViewController desde un viewController, luego se llamará a viewWillAppear para el viewController presentado.
fuente
Mi problema era que no se llamaba a viewWillAppear al desconectar de una transición. La respuesta fue poner una llamada a viewWillAppear (verdadero) en la secuencia de desenrollado en el Controlador de vista al que regresa
@IBAction func desenrollar (para desenrollarSegue: UIStoryboardSegue, ViewController laterVC: Cualquiera) {
fuente
No estoy seguro de que sea el mismo problema que resolví.
En algunas ocasiones, el método no se ejecuta de forma normal como "[self methodOne]".
Tratar
fuente
viewWillAppear
que no se llama en absolutoSolo debe tener 1 UIViewController activo en cualquier momento. Cualquier subvista que desee manipular debe ser exactamente eso, subVIEWS, es decir, UIView.
Utilizo una técnica simple para administrar mi jerarquía de vistas y aún no he encontrado un problema desde que comencé a hacer las cosas de esta manera. Hay 2 puntos clave:
¿Qué quiero decir con "el valor de una pantalla"? Es un poco vago a propósito, pero generalmente es una característica o sección de su aplicación. Si tiene algunas pantallas con la misma imagen de fondo pero diferentes superposiciones / ventanas emergentes, etc., debería ser 1 controlador de vista y varias vistas secundarias. Nunca debería encontrarse trabajando con 2 controladores de vista. Tenga en cuenta que aún puede crear una instancia de una UIView en un controlador de vista y agregarla como una subvista de otro controlador de vista si desea que ciertas áreas de la pantalla se muestren en varios controladores de vista.
En cuanto a UINavigationController, ¡este es tu mejor amigo! Apague la barra de navegación y especifique NO para animación, y tendrá una excelente manera de cambiar de pantalla a pedido. Puede empujar y desplegar controladores de vista si están en una jerarquía, o puede preparar una matriz de controladores de vista (incluida una matriz que contenga un solo VC) y configurarla para que sea la pila de vistas usando setViewControllers. Esto le brinda total libertad para cambiar VC, mientras obtiene todas las ventajas de trabajar dentro del modelo esperado de Apple y hacer que todos los eventos, etc., se activen correctamente.
Esto es lo que hago cada vez que inicio una aplicación:
(tenga en cuenta que comenzar desde una ventana es solo una preferencia personal; me gusta construir cosas yo mismo, así que sé exactamente cómo se construyen. Debería funcionar bien con la plantilla basada en vistas)
Todos los eventos se disparan correctamente y básicamente la vida es buena. Luego, puede dedicar todo su tiempo a escribir las partes importantes de su aplicación y no perder el tiempo tratando de piratear manualmente las jerarquías de vistas para darle forma.
fuente