2
votes

I have a UINavigationController with a UIViewController (VC1) pushed onto it. VC1 contains a collectionView. When a user taps a cell, a child viewController (VC2) is added to VC1.

VC2 should support all orientations. Whereas VC1 only supports portrait orientation. In portrait mode, I want to be able to present VC2, rotate into landscape, have VC2 adjust its layout accordingly, dismiss VC2, revealing VC1 still in portrait orientation/layout.

The shouldAutorotate method in VC2 gets called when VC2 is presented using the stock method. However this is insufficient because it doesn't allow a custom transition:

(1)

- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
{
    CommentsViewController *vc = [[CommentsViewController alloc] initWithNibName:@"CommentsViewController" bundle:nil];

    [self presentViewController:vc animated:YES completion:nil];
}

The shouldAutorotate method is NOT called when using presentViewController:animated:completion: with a custom transition or using traditional viewController containment methods. In other words, neither of these work:

(2)

- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
{
    CommentsViewController *vc = [[CommentsViewController alloc] initWithNibName:@"CommentsViewController" bundle:nil];
    self.transitioningDelegate = [[TransitioningDelegate alloc] init];
    vc.modalPresentationStyle = UIModalPresentationCustom;
    vc.transitioningDelegate = self.transitioningDelegate;

    [self presentViewController:vc animated:YES completion:nil];
}

(3)

- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
{
    CommentsViewController *vc = [[CommentsViewController alloc] initWithNibName:@"CommentsViewController" bundle:nil];

    [self addChildViewController:vc];
    vc.view.frame = self.view.bounds;
    [self.view addSubview:vc.view]; // Assume I'm doing a cool custom animation here
    [vc didMoveToParentViewController:self];
}

In summary, using approach #1 the rotation methods are called properly. But using #2 and #3 they are not. This prohibits me from building the required custom transition because doing so would mean the child viewController not supporting all orientations.

Any help would be much appreciated.

For background: I am versed in iOS6/7 rotation APIs, UIViewController containment, and custom viewController transitions.

Edit:

I did implement shouldAutomaticallyForwardRotationMethods to no avail.

2

2 Answers

1
votes

So, this might not be what you need, but it seems like the presenting view controller maintains control of the shouldAutorotate call if your animated transition does not remove the presenting view controller's view. If you do remove the presenting view controller's view, then the control of the shouldAutorotate call moves up to the presented view controller.

I'm not sure how to send control automatically up without removing the view (so that you can show a transparent view), but you could just forward the shouldAutorotate call manually:

- (BOOL) shouldAutorotate{
    if(self.presentedViewController){
        return [self.presentedViewController shouldAutorotate];
    }
    return YES;
}

Not the most ideal though.

-1
votes

Did you happen to implement - (BOOL)shouldAutomaticallyForwardRotationMethods on the parent controller and have it return NO?

You case may be more complex, since you support different rotations for the different parent and child view controllers, but this is a easy gotcha to miss.