iphone - Cómo identificar que se presenta un UIViewController
ios objective-c (10)
He creado una subclase UIViewController que puede ser empujada en una pila de navegación de un UINavigationController o presentada (modalmente) desde cualquier UIViewController. Necesito identificar si se presenta mi controlador de vista; si aparece, debo agregar una barra de herramientas con un botón de cierre en la parte superior del controlador de vista. (de lo contrario, si se empuja en la pila de navegación, entonces se agregará el botón de cierre predeterminado, con el uso de ese usuario puede regresar).
En todas las versiones disponibles, digamos 4.3, 5.0, hasta 6.0, desde dentro de una subclase UIViewController. ¿Puedo suponer que el controlador de vista se presenta (modalmente) si se cumple la siguiente condición?
if(self.parentViewController == nil || self.navigationController == nil)
@saikamesh.
A medida que usa UINavigationController para navegar por sus viewControllers, creo que puede usar topViewController
( Doc aquí ) y visibleViewController
( Doc nuevamente ) para alcanzar su intención.
Usted menciona que:
cuando se empuja en la pila de navegación, entonces se agregará el botón de cierre predeterminado, al usar que el usuario puede regresar
Si la instancia del UIViewController específico es importante, creo que es mejor crear una instancia de singleton compartida y proporcionar una marca presentada global:
id specificVC = [SpecificViewController sharedInstance];
if (specificVC.isPushed) {
[self.navController popToViewController:specificVC animated:YES];
}
y comprobar si se presenta:
if ([self.navController.visibleViewController isKindOfClass:[SpecificViewController class]]) {
// Hide or add close button
self.isPresented = YES;
}
O bien, puede leer la respuesta muy aceptada .
:) La esperanza ayuda.
Con iOS 5, UIViewController obtuvo una propiedad de solo lectura llamada presentViewController, que reemplaza la semántica más antigua de parentViewController
(que ahora describe la contención ). Esta propiedad se puede usar cuando un controlador de vista necesita acceder al controlador de vista que lo presenta. Nota: ¡esto a menudo será algo diferente de lo que usted esperaría, si es nuevo en la API!
Además, la propiedad isBeingPresented
se introdujo para resolver prácticamente la clase de situaciones en las que se encuentra actualmente. Verifique esta propiedad en la vista del controlador de viewWillAppear:
. viewWillAppear:
Actualizar
He leído que pareces apuntar a iOS 4.3 también:
En ese caso, debe proteger la llamada a isBeingPresented
con un if ([self respondsToSelector:…])
en el bloque else
verificar si el parentViewController no es nulo.
Otro enfoque para la compatibilidad con versiones anteriores podría ser anular +resolveInstanceMethod:
agregar una implementación para -isBeingPresented
en tiempo de ejecución. Esto dejará sus sitios de llamadas limpios, y se deshará de Runtime-Magic tan pronto como deje de usar el antiguo soporte de iOS ;-)
Tenga en cuenta, sin embargo, que hay casos de ventaja en esto, y su enfoque inicial también, cuando se ejecuta en iOS <5:
El controlador de vista se puede presentar contenido en cualquier otro controlador de vista, incluidos los controladores de navegación. Cuando sucede ese último caso, no tienes suerte: parentViewController
será nil
, mientras que navigationController
no . Puedes intentar agregar muchos códigos difíciles de manejar para mitigar esta limitación en iOS más antiguos ... o simplemente puedes dejarlo pasar.
En cualquier momento puede verificar si tiene un controlador de vista modal presentado o no utilizando la propiedad modalViewController desde su controlador de navegación. Ex:
UIViewController *presentedController = self.navigationController.modalViewController;
if (presentedController) {
// At this point, you have a view controller presented from your navigation controller
if ([presentedController isKindOfClass:[controllerYouWantToCheck class]]) {
// add your toolbar/buttons/etc here
}
}
Para manejar este tipo de comportamiento, generalmente establezco / reinicio un BOOL alternándolo en los métodos viewWillAppear / viewWillDisappear.
Por cierto, su condición de prueba parece incorrecta. Creo que deberías usar
if(self.parentViewController != nil || self.navigationController != nil)
¿Por qué no puedes simplemente agregar la barra de herramientas a tu controlador de vista? ¿Hay algún caso en que la vista esté cargada pero nunca presentada?
Podrías hacerlo así, es rápido y seguro.
UIViewController *topController = [UIApplication sharedApplication].keyWindow.rootViewController;
// Find the top controller on the view hierarchy
while (topController.presentedViewController) {
topController = topController.presentedViewController;
}
// If the top controller it is not already presented
if (![topController isKindOfClass:[YourViewController class]]) {
// Present it
[topController presentViewController:yourViewController animated:YES completion:nil];
}
else {
// do some stuff here
}
Por favor, marque de esta manera:
for (UIViewController*vc in [self.navigationController viewControllers]) {
if ([vc isKindOfClass: [OffersViewController class]]){ //this line also checks OffersViewController is presented or not
if(vc.isViewLoaded){
NSLog(@"Yes");
}
}
}
Si fuera yo, tendría un método de inicio personalizado y lo utilizaría al crear el vc.
vc = [[[MyUIViewControllerSubClass alloc] init] initWithToolbarAndCloseButton:YES];
Tuve un caso similar, sin embargo, el controlador de vista que presenté está envuelto en su propio controlador de navegación . Así que en ese controlador de vista, cuando necesito determinar si debo agregar o no el botón de cierre frente al botón de retroceso, solo reviso el tamaño de pila de los controladores de navegación . Si se presenta la pantalla, el tamaño de la pila debe ser uno (necesita botón de cierre) ... y si se empuja con un controlador de navegación existente, entonces el tamaño de la pila será mayor que uno (se necesita el botón de retroceso).
BOOL presented = [[self.navigationController viewControllers] count] == 1;
Una respuesta elegante que no he visto aquí:
// Edit: Added 2 other modal cases
extension UIViewController {
var isModal: Bool {
return self.presentingViewController?.presentedViewController == self
|| (navigationController != nil && navigationController?.presentingViewController?.presentedViewController == navigationController)
|| tabBarController?.presentingViewController is UITabBarController
}
}
crédito: basado en esta esencia
Utilizo este código para verificar si se presenta el UIViewController.
if (uiviewcontroller.presentingViewController != nil) {
// do something
}