Presentando un control de semitransparente que funciona tanto en iOS7 como en iOS8

Tenía el siguiente código que funcionaba perfectamente en iOS7.

[UIView animateWithDuration:0.5 animations:^(void) { self.view.alpha = 0.5; [self.navigationController.navigationBar setAlpha:0.3]; }]; //to make the background view controller semi-transparent UIViewController *rootViewController = [UIApplication shanetworkingApplication].delegate.window.rootViewController; [rootViewController setModalPresentationStyle:UIModalPresentationCurrentContext]; OverlayViewController *ctlr = [storyBoard instantiateViewControllerWithIdentifier:@"OverlayViewController"]; //present the OverlayViewController [self presentViewController:ctlr animated:YES completion:nil]; 

Luego, tenía el siguiente en vista: Aparecerá el controller de vista de background, para volver atrás su vista a opaco completo.

 [UIView animateWithDuration:1.0 animations:^(void) { self.view.alpha = 1.0; [self.navigationController.view setAlpha:1.0]; }]; 

Ahora, con iOS8, el código anterior no establece que el background sea semitransparente. El color negro rodea el OverlayViewController.

Encontré en línea que usar UIModalPresentationOverCurrentContext dará el comportamiento esperado. Realmente sí, pero el controller de vista de background nunca se quita de la jerarquía de vista (editado para agregar reference a este comportamiento: https://developer.apple.com/documentation/uikit/uimodalpresentationstyle ). Entonces, el viewWillAppear nunca se llama, por lo que la semi-transparencia nunca se elimina.

Obviamente, puedo recurrir a hacks como usar NSNotificationCenter e iniciar una notificación cuando se elimina el OverlayViewController, pero se siente como una forma indirecta de hacer lo que debería ser simple. ¿Hay alguna otra forma en que pueda lograrlo con gracia?

Preguntas corolarias:

1) Si UIModalPresentationOverCurrentContext es la única manera de lograr esto, me pregunto si me vería obligado a poner dos versiones del código para que funcione tanto en iOS7 como en iOS8.

2) Obviamente, esa nueva enumeración no se reconoce en las versiones anteriores de Xcode. Entonces, ¿debería actualizar mi equipo a Xcode 6 solo para asegurarse de que puedan ejecutar este código, incluso si el rest de su trabajo se centra solo en iOS7? ¿O hay alguna manera de decirle a la versión anterior de Xcode que ignore el bloque de código particular que solo se necesita para iOS8?

Tienes que manejar dos configuraciones para iOS 7 y iOS8. En ambos casos, debe asegurarse de que el control de vista en segundo plano no se retira de la jerarquía de vista. Esto se puede lograr con:

  1. En iOS7, establezca el indicador UIModalPresentationCurrentContext en UIModalPresentationCurrentContext para el controller de vista presentadora . self.navigationController identificar quién es el controller de vista de presentación: no necesariamente es el controller de self.navigationController si tiene varios controlleres de vista de contenedor.

  2. En iOS8, establezca el indicador UIModalPresentationOverCurrentContext en UIModalPresentationOverCurrentContext para el controller de vista presentado . Si está utilizando Storyboard, asegúrese de que el estilo de presentación esté configurado como Pnetworkingeterminado para el storyboard segue y, dentro del método prepareForSegue , establezca el estilo de presentación en el controller de vista de destino en UIModalPresentationOverCurrentContext .

Ahora para responder a sus preguntas con corolario:

1) Necesita tener código para manejar ambas situaciones en iOS7 y iOS8:

Defina algunas macros para verificar el número de versión en que se ejecuta la aplicación. Por ejemplo, lo siguiente hará:

 #define SYSTEM_VERSION_EQUAL_TO(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrdenetworkingSame) #define SYSTEM_VERSION_GREATER_THAN(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrdenetworkingDescending) #define SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrdenetworkingAscending) #define SYSTEM_VERSION_LESS_THAN(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrdenetworkingAscending) #define SYSTEM_VERSION_LESS_THAN_OR_EQUAL_TO(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrdenetworkingDescending) 

2) Obviamente, si tiene un código que necesita comstackrse en iOS7 y iOS8, su equipo necesita actualizar a la última versión de XCode "XCode 6.1 a partir de ahora.

En Swift para iOS 8.x:

al configurar UIModalPresentationStyle.OverCurrentContext al viewController que se presenta, se realiza el trabajo.

  func presentTransparentController(){ var viewController = self.storyboard?.instantiateViewControllerWithIdentifier("ViewControllerNamed") as! ViewController // set to .OverCurrentContext viewController.modalPresentationStyle = UIModalPresentationStyle.OverCurrentContext // presents the view controller as usual self.presentViewController(viewController, animated: true, completion: nil) } 

Basado en la respuesta de @ Tiguero, creé una class de categoría pequeña para resolver el problema.

 @implementation UIViewController (Extensions) - (void) presentTransparentViewController:(UIViewController *)viewControllerToPresent animated:(BOOL)flag completion:(void (^)(void))completion { if(SYSTEM_VERSION_LESS_THAN(@"8.0")) { self.parentViewController.navigationController.modalPresentationStyle = UIModalPresentationCurrentContext; }else{ viewControllerToPresent.modalPresentationStyle = UIModalPresentationOverCurrentContext; } [self presentViewController:viewControllerToPresent animated:YES completion:completion]; } @end 

La versión de iOS7 me obligó a codificar el controller que hace la presentación.