iOS: ¿Hay alguna forma de descubrir el controlador de vista que se muestra en la pantalla en la aplicación sin usar viewWillAppear / viewWillDisappear?

Desafortunadamente, no hay una forma directa de averiguarlo, y dependerá de su jerarquía de vistas.

El problema principal es que potencialmente puede tener más de un controlador de vista en la parte superior. Esto es especialmente cierto con el iPad, pero incluso puede ser el caso en el iPhone. No hay nada que le impida utilizar su controlador de vista personalizado para contener otros controladores de vista, y esto no necesariamente estaría expuesto de ninguna manera.

Entonces, llega a tener que saber cómo es su jerarquía de navegación, y usar eso para determinar qué hay encima.

Si está utilizando los controladores de contenedores de Apple, UINavigationController tiene una propiedad topViewController; UITabBarController ha seleccionado ViewController, y así sucesivamente.

Si está utilizando sus clases personalizadas, puede proporcionar su propia forma de determinar el controlador de vista superior.

Sin embargo, incluso esto no es suficiente. Por ejemplo, puede mostrar un controlador de vista modal, que sería un caso separado.

Como puede ver, no hay una solución trivial. Si comparte exactamente lo que está tratando de lograr, tal vez podamos encontrar una solución alternativa. Por ejemplo, tal vez solo necesite la vista superior, y eso podría tener una respuesta más simple.

Puede usar la propiedad contentView de su UIWindow: [myWindow contentView].

Según los documentos de Apple Cocoa, `contentView`:
Devuelve la vista de contenido de la ventana, el objeto NSView más accesible en la jerarquía de vista de la ventana.

En realidad, a menudo hay muchos controladores de vista en la pantalla a la vez. Puede acceder al nivel superior a través de la propiedad rootViewController de UIWindow, y luego acceder a cualquier controlador de vista que muestre a través de su propiedad childViewControllers, y acceder a sus hijos a través de sus propiedades childViewControllers, y así sucesivamente. Si recorre recursivamente todas estas propiedades childViewControllers, puede examinar o recopilar todos los controladores de vista que están actualmente visibles.

Sin embargo, generalmente hay una mejor manera de hacer lo que estás tratando de hacer:

  • Si está tratando de recordar qué pantalla es visible para poder volver a ella cuando el usuario se reinicie, las API de restauración de estado de Cocoa Touch están diseñadas para hacerlo.
  • Si desea verificar una barra de pestañas o un controlador de navegación en particular, conecte ese controlador a una toma de corriente para poder acceder a él más tarde. Si desea que se le informe cuando uno cambia de pantalla, ambos tienen delegados que reciben esa información.
  • Si desea encontrar un controlador de vista particular para que pueda saber si alguna parte de su modelo se ha actualizado, transmita la actualización a través de NSNotificationCenter y deje que el controlador de vista observe esa notificación.

Recorrer la jerarquía del controlador de vista es inherentemente más lento, más frágil y más difícil que usar una API diseñada para la tarea en cuestión.

Puede crear su propio administrador entonces. Normalmente uso Singletons para esto. En viewDidLoad, puede guardar la vista usando enumeraciones o pasando `this` al singleton que almacenará el valor de la vista actual. Hice lo mismo en la mayoría de mis aplicaciones de Android, iOS y C ++.

Bueno, viewWillAppear y viewWillDisappear están diseñados para lo que estás haciendo. Puede rastrear la jerarquía de vistas como sugirió otra persona, pero eso parece indirecto y un código potencialmente defectuoso.

¿Quiere decir que está tratando de encontrar viewController con foco? Muy a menudo hay más de un viewController en la pantalla. Si ese es el caso, mire la propiedad “enfocada”.