Container controllers and viewWillTransitionToSize:

Hi,


I have been using Autolayout and size classes for a while, but I still seem to get confuse with how viewWillTransitionToSize: and sizeForChildContentContainer: work when used in custom container controllers and in container views with Interface Builder.


My specific question is: how do you calculate a child controller size defined with constraints? (for -sizeForChildContentContainer:withParentContentSize: ) moreover when -viewWillTransitionToSize: run before the constraint and layout cycle.


By default viewWillTransitionToSize:withTransitionCoordinator seems to perform the following (more things seems to be going on with presentedViewControllers, but it is not important for the matter at hand).

- (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id <UIViewControllerTransitionCoordinator>)coord
{
    for (UIViewController* child in self.childViewControllers
    {
          CGSize const childSize = [self sizeForChildContentContainer:child withParentContentSize:size];
          [child viewWillTransitionToSize:childSize withTransitionCoordinator:coord];
    }
}

If you don't override -sizeForChildContentContainer:withParentContentSize:, the method will simple return what you pasted as the parent content size. Meaning that the childVCs will have the same size as the parentVC. That is wrong for most cases, and that is why one should override -sizeForChildContentContainer: and calculate the proper size. However -viewWillTransitionToSize: will run before the updateConstraint and layout cycle (marked subtely by the "will" prefix of the method name).


So, if you define the position of your childVCs or containerVCs with constraints (whether in Interface Builder or by code). There seems to be no way to pass the proper size down the chain of -viewWillTransitionToSize:withTransitionCoordinator:


Am I missing something?

Thanks beforehand.

The method you are looking for is - systemLayoutSizeFittingSize:withHorizontalFittingPriority:verticalFittingPriority: which will calculate the size of the receiving view based on the constrains applied to that view and its subviews.

Hi Dex,

Thank you for your answer. That seems to do the trick for custom views. However, I found two hiccups:

  • When using Interface Builder and Container Views (to add ViewControllers). I don't seems to get a proper sizing. Even querying the content controller's view superview -systemLayoutSizeFittingSize: (since container views are views by itself that has the controller's view as subview).
  • If the traits changes when, for example, rotating the iPhone screen, the size will obviously change too. However, in the -viewWillTransitionToSize: and -sizeForChildContentContainer: the activated constraints will be the ones for the size that is not yet rotated. Thus the sizing returned will be wrong. You can call updateConstriantsIfNeeded, but the traits haven't yet changed.

Any ideas on how to overcome these problems.

1) Not sure why querying the fitting size of the child view controller's view won't produce the correct result. Querying the container definently will not, so that's not a surprise. I'd try using the containment API (set up the containment programatically) instead of the embed segue.


2) What about -willTransitionToTraitCollection:coordinator:? Be sure to invoke the super's implementation first.

Container controllers and viewWillTransitionToSize:
 
 
Q