Child View Controller rotation methods not being called
Asked Answered
R

2

10

Summary

I am attempting to add a child view controller to a parent view controller, and have the parent view controller inform the child view controller of rotation events. However, the rotation messages are not being forwarded to the child view controller (which is the default behavior). Why is this default behavior not occurring?

Environment: iOS 7, XCode 5, OSX 10.9

Details:

I am implementing a custom container view controller following instructions in the Apple Document: "Creating Custom Container View Controllers". I am attempting to establish a simple parent child relationship that forwards rotation events. The total hierarchy is exactly as pictured in the documentation figure 14-1 redrawn here:

ParentViewController --------> RootView
        |                       /   \
        |                      /     \
        ˅                     /       \
ChildViewController ---> ChildView     \ 
                                        \   
                                    OverLayView

I am accomplishing this using the code from the document Listing 4-1 in the parentViewController (unityViewController = childViewController, unityView = childView):

// In the ParentViewController    
// Called by the Application Delegate in application:didFinishLaunchingWithOptions:
- (void)addUnityViewController:(UIViewController *)unityViewController withUnityView:(UIView *)unityView
{
    [self addChildViewController:unityViewController]; // 1. Establish Child parent relationship

    unityView.frame = self.view.frame;                 // 2. Set the frame (explicitly or with constraints)
    [self.view addSubview:unityView];                  // 2.1 Add the subview AFTER you set the frame
    ... // add some view constraints here

    [self.view sendSubviewToBack:unityView];           // In the back, but not completely obstructed by any other views
    [unityViewController didMoveToParentViewController:self];// 3. Tell the child what happened
}

This code successfully displays the child view as a subview of the RootView with the OverlayView adding some functional buttons. However, when the device rotates, the parent view controller rotates its views successfully, but does not forward the rotation messages to the child view controller (unityViewController) resulting in an improperly displayed childView (unityView) in the rootView. According to "Creating Custom Container View Controllers" this should happen automatically:

Customizing Appearance and Rotation Callback Behavior: Once you add a child to a container, the container automatically forwards rotation and appearance callbacks to the child view controllers as soon as an event occurs that requires the message to be forwarded.

To ensure that this should be happening, I overrode the following methods:

// In the parent ViewController:
- (BOOL)shouldAutorotate
{
    return YES;
}

- (BOOL)shouldAutomaticallyForwardAppearanceMethods
{
    return YES;
}

- (BOOL)shouldAutomaticallyForwardRotationMethods
{
    return YES;
}

However, the willRotateToInterfaceOrientation:duration: and didRotateFromInterfaceOrientation: methods in the child viewController (unityViewController) are never being called. I have been able to confirm that the parent methods are indeed being called, and in those I make the call to super, but the child methods are never called.

Question:

What is the reason that this default behavior is not occurring? I need both the parent and the child to receive the rotation messages for proper display.

Note: I am aware that I can manually make the calls to these methods in the parent, but I do not want to manually make these calls and add extra code that should be default behavior.

Thank you so much for the help!

Rosemaryrosemond answered 28/3, 2014 at 17:46 Comment(1)
I'm wondering if you're actually seeing counter-rotations on the views: that is, the parent rotating one way while the child rotates another. Try returning NO on all the shouldAutorotate methods to see if it looks any different. If it does, it means that the views are, in fact rotating -- just not how you'd expect.Agnosticism
J
5

In order for your child view controller to receive forwarded orientation callbacks, it must be visible. It's likely that your child view controller isn't visible because its view hasn't been added into the view hierachy.

If you change your method to this, you should start seeing your rotation messages being called:

- (void)addUnityViewController:(UIViewController *)unityViewController 
{
    [self addChildViewController:unityViewController];

    unityViewController.view.frame = self.view.bounds;
    [self.view addSubview:unityViewController.view];
    ... // add some view constraints here

    [self.view sendSubviewToBack:unityViewController.view];       
    [unityViewController didMoveToParentViewController:self];
}

For more information: Responding to Orientation Changes in a Visible View Controller.

Jaysonjaywalk answered 23/5, 2014 at 5:34 Comment(0)
C
5

You may have to set the AutoresizingMask on the child view:

[childView setAutoresizingMask: UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight];

This makes sure the view resizes with it's parent view during rotation.

Carpus answered 18/9, 2014 at 17:43 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.