Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Custom presented UIViewController changing to fullscreen

I have a view controller presented using UIModalPresentationCustom presentation style. I use a custom UIViewControllerTransitioningDelegate to present the view controller as a sidebar (so it slides in from the edge of the screen and does not occupy the full screen).

However when I then present another view controller from this one using UIModalPresentationFullScreen — and then dismiss the full screen view controller, my underlying custom presented controller is suddenly resized to occupy the full screen. Does anyone know why this is the case?

Edit: this is essentially my animateTransition method for presenting the sidebar — I've stripped out most of the code to make it readable. Basically it gets the container from the transitionContext, adds and animates the destination view controller's view to the container.

- (void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext
{
    UIView *container = transitionContext.containerView;

    UIViewController *fromVC = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
    UIViewController *toVC = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
    UIView *fromView = fromVC.view;
    UIView *toView = toVC.view;

    if( toVC.isBeingPresented )
    {
        [container addSubview:toView];

        //... Animate some new frame for toView            

        //Call [transitionContext completeTransition:YES] on animation completion
    }
    else
    {
        //... Animate fromView out

        //On completion remove fromView from superview

        //Call [transitionContext completeTransition:YES] on animation completion
    }
}

Edit 2: Doing a little more research, I notice that the frame of my custom presented view controller's view is being set when the view controller above it in the modal stack is dismissed. The following stack trace leads to the frame being set as full screen:

0 -[MyCustomPresentedViewControllerView setFrame:]
1 -[UIView(MPAdditions) setFrameOrigin:]
2 -[UIViewControllerAccessibility(SafeCategory) dismissViewControllerWithTransition:completion:]
3 -[UIViewController dismissViewControllerAnimated:completion:]
like image 667
simeon Avatar asked Aug 10 '14 04:08

simeon


People also ask

How do I make ViewController full screen?

Present ViewController in full screen To prevent this, the presentation style can be changed. To present the DetailViewController full screen, the modalPresentationStyle property of a view controller must be set to . fullScreen before it will be presented.

What is the difference between UIView and UIViewController?

They are separate classes: UIView is a class that represents the screen of the device of everything that is visible to the viewer, while UIViewController is a class that controls an instance of UIView, and handles all of the logic and code behind that view.


2 Answers

Changing the presentation style by assigning:

viewController.modalPresentationStyle = UIModalPresentationOverCurrentContext;

results in the modal presentation controller occupying a fraction of the screen, the same fraction as the original presented view controller of the UIPresentationController.

However, using
viewController.modalPresentationStyle = UIModalPresentationOverFullScreen
is better for this case, since his modal controller is full screen.

like image 166
SwiftMatt Avatar answered Sep 23 '22 02:09

SwiftMatt


I am experiencing the same issue. I've tried debugging it using symbolic breakpoints and there seem to be some internal call on some kind of layout manager that does this.

While I wasn't able to "solve" this (it seems to me like a bug in the SDK), I was able to come up with a workaround that fixes this. Basically, you have to set the correct dimensions of the presented view at two opportune times. Like this:

In the view controller that was presented using your custom UIPresentationController, add this:

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    dispatch_async(dispatch_get_main_queue(), ^{
        self.view.frame = [self.presentationController frameOfPresentedViewInContainerView];
    });
}

- (void)viewDidAppear:(BOOL)animated {
    [super viewDidAppear:animated];
    self.view.frame = [self.presentationController frameOfPresentedViewInContainerView];
}

And if you are wondering: yes, you do need it to do in two places. Because weirdly enough, when I did it only in the viewDidAppear async block, it got broken (resized to fullscreen) once the animation finished.

like image 34
Lukas Petr Avatar answered Sep 22 '22 02:09

Lukas Petr