ios objective-c uiviewcontroller presentviewcontroller uipresentationcontroller

ios - Cuadro incorrecto al descartar el controlador de vista presentado modalmente



objective-c uiviewcontroller (5)

Estoy presentando un UIViewController utilizando una transición personalizada y un UIPresentationController personalizado. La vista del controlador de vista no cubre toda la pantalla, por lo que el controlador de vista de presentación aún está visible.

A continuación, presento una instancia de UIImagePickerController en la parte superior de este controlador de vista. El problema es que cuando descarto el selector de imagen, el marco del controlador de vista de presentación cubre toda la pantalla en lugar de solo la parte que quiero que cubra. El marco especificado por frameOfPresentedViewInContainerView en mi UIPresentationController personalizado parece ser completamente ignorado.

Solo si se presenta el selector de imagen con un modalPresentationStyle of UIModalPresentationOverCurrentContext mis marcos permanecen intactos (lo que tiene sentido ya que no se eliminan vistas de la jerarquía de vistas en primer lugar). Lamentablemente eso no es lo que quiero. Quiero que el selector de imágenes se presente en pantalla completa, lo que, por cualquier motivo, parece desordenar mi diseño. ¿Algo que pueda estar haciendo mal o olvidando aquí? ¿Alguna sugerencia?


Esto funcionó para mí, en UIPresentationController :

override func containerViewWillLayoutSubviews() { super.containerViewWillLayoutSubviews() presentedViewController.view.frame = frameOfPresentedViewInContainerView }


Esto se espera porque la presentación a pantalla completa no restaura el marco original calculado por frameOfPresentedViewInContainerView . La forma recomendada de solucionar este problema es crear una vista de contenedor en la que insertará la vista del controlador de vista presentada. Aquí está el código relevante para su controlador de presentación personalizado:

- (void)presentationTransitionWillBegin { // wrapper is a property defined in the custom presentation controller. self.wrapper = [UIView new]; [self.wrapper addSubview:self.presentedViewController.view]; } - (CGRect)frameOfPresentedViewInContainerView { CGRect result = self.containerView.frame; // In this example we are doing a half-modal presentation CGFloat height = result.size.height/2; result.origin.y = height; result.size.height = height; return result; } - (UIView *)presentedView { return self.wrapper; } - (BOOL)shouldPresentInFullscreen { return NO; } - (void)containerViewWillLayoutSubviews { self.wrapper.frame = self.containerView.frame; self.presentedViewController.view.frame = [self frameOfPresentedViewInContainerView]; }

Tenga en cuenta que reemplazamos presentedView para devolver la vista del contenedor en lugar del valor predeterminado: la vista del controlador de la vista presentada. De esta manera, incluso si la segunda presentación modifica el marco del contenedor, la vista del controlador de vista presentada no cambiará.


Probé containerViewWillLayoutSubviews pero no funcionó del todo. Quería evitar las vistas de envoltorio extra si es posible. Se me ocurrió esta estrategia de corregir el marco en la vista utilizando presentedView . Además, pude eliminar containerViewWillLayoutSubviews . forceFrame está en sintonía con nuestro caso de uso particular. presentedFrame es establecido por nuestro animador personalizado.

class CustomModalPresentationController: UIPresentationController { var presentedFrame = CGRect.zero var forceFrame = false override func dismissalTransitionWillBegin() { forceFrame = false } override func presentationTransitionDidEnd(_ completed: Bool) { forceFrame = true } override var presentedView: UIView? { if forceFrame { presentedViewController.view.frame = presentedFrame } return presentedViewController.view } override var frameOfPresentedViewInContainerView: CGRect { return presentedFrame } }


Probé los dos enfoques de envoltura mencionados. Un efecto secundario del uso de este enfoque de ajuste es que la rotación del dispositivo no se muestra bien, introduciendo cuadros negros alrededor de la vista presentada.

En lugar de hacer el truco de ajuste, intente configurar el modalPresentationStyle de modalPresentationStyle del UIImagePickerController presentado en UIModalPresentationOverFullScreen . Esto significa que las vistas que se encuentran debajo del selector de imágenes no se eliminarán ni se restaurarán de la jerarquía de vistas durante la presentación / cancelación.


La solución de Erudel no funcionó para mí tal como está, pero agregar otra vista entre wrapperView y wrapperView hizo el truco (no tengo idea por qué):

- (instancetype)initWithPresentedViewController:(UIViewController *)presentedViewController presentingViewController:(UIViewController *)presentingViewController { if (self = [super initWithPresentedViewController:presentedViewController presentingViewController:presentingViewController]) { _wrapperView = [[UIView alloc] init]; _wrapperView2 = [[UIView alloc] init]; // <- new view } return self; } - (CGRect)frameOfPresentedViewInContainerView { return self.containerView.bounds; } - (UIView *)presentedView { return self.wrapperView; } - (BOOL)shouldPresentInFullscreen { return NO; } - (void)containerViewWillLayoutSubviews { self.wrapperView.frame = self.containerView.frame; self.wrapperView2.frame = /* your custom frame goes here */; self.presentedViewController.view.frame = self.wrapperView2.bounds; } - (void)presentationTransitionWillBegin { [self.wrapperView addSubview:self.wrapperView2]; [self.wrapperView2 addSubview:self.presentedViewController.view]; // Set up a dimming view, etc }

Probado esto en iOS 9.3.