iosuiviewcontrollerscreen-rotationsafearealayoutguide

Why is the logic of retrieving SafeAreaInsets in `viewWillTransitionToSize` slightly wrong?


I'm exploring if the landscape "Safe Area insets" can be presicely known in viewWillTransitionToSize when rotating from Portrait to Landscape.

I've seen this SO answer, its code is rather a pseudocode: https://stackoverflow.com/a/46581783/2567725

On my iPhone XR insets are {48, 0, 34, 0} for portrait and {0, 48, 21, 48} for Landscape. Like this: enter image description here

When rotating a device - from Portrait to Landscape - I log the "future" insets in animateAlongsideTransition, and they are correct. The question is, why those correct values are retrieved from FromViewControllerKey, not from ToViewControllerKey:

- (void)logSafeAreaInsets:(id<UIViewControllerTransitionCoordinatorContext>)context
{
    UIInputViewController* vcFrom = [context viewControllerForKey:UITransitionContextFromViewControllerKey];
    UIEdgeInsets iiFrom = vcFrom.view.safeAreaInsets;
    UIInputViewController* vcTo = [context viewControllerForKey:UITransitionContextToViewControllerKey];
    UIEdgeInsets iiTo = vcTo.view.safeAreaInsets;
    NSLog(@"TADAM from=%@ to=%@", NSStringFromUIEdgeInsets(iiFrom), NSStringFromUIEdgeInsets(iiTo));
}

- (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator
{
    [super viewWillTransitionToSize:size withTransitionCoordinator:coordinator];
    
    [coordinator animateAlongsideTransition:^(id<UIViewControllerTransitionCoordinatorContext>  _Nonnull context) {
        
        [self logSafeAreaInsets:context];
        
    } completion:^(id<UIViewControllerTransitionCoordinatorContext>  _Nonnull context) {
            
    }];
}

And for ToViewControllerKey they are {0, 0, 0, 0} ! The logs look like this:

TADAM from={0, 48, 21, 48} to={0, 0, 0, 0}

As I understand, ToViewControllerKey is a Landscape VC (after rotation), and FromViewControllerKey is a Portrait VC (before rotation).

So I can get what I want UIViewControllerTransitionCoordinatorContext, but its logic seems wrong:

  1. Why real Landscape insets are retrieved from FromVC, not from ToVC ?
  2. Why insets for ToVC are zero in animateAlongsideTransition?

Solution

  • Well, the logic isn't "slightly wrong", it's just undocumented. As it turned out, vcTo is nil in my code. So insets are zero. vcTo is nil because screen rotation animation is done with only one VC, unlike e.g. transitioning animation when pushing/presenting a new VC.

    I guess that vcFrom has already Landscape insets in animateAlongsideTransition because of difference btw the model layer tree and the presentation layer tree - while I don't know yet how to check this assumption.