Question

I feel like I'm missing something obvious.

I've got a custom segue class. It does some animation. It works just fine if the current orientation is the same as the nib's orientation, but I can't make it work if the current orientation doesn't match the nib (ie current orientation is landscape but nib is portrait).

The issue is that the destination view controller's frame and orientation is wrong until viewDidAppear. But viewDidAppear is too late. Any attempt to do animation inside the custom segue must happen before viewDidAppear.

Oddly, viewDidLoad and viewWillAppear report the correct self.interfaceOrientation (while unfortunately reporting the wrong frame), but any attempt to draw in these methods will draw at the wrong orientation.

Anyone want to call me an idiot and point out the obvious mistake I'm making? I would greatly appreciate.

Was it helpful?

Solution

To answer my own question, I ultimately gave up on custom segues and opted for using a custom container controller. This doesn't get around the problem of view controllers not knowing their proper frame until after appearing, but did simplify the problem.

A more direct answer to my question is that it's the responsibility of the container controller (or presenting controller) to change the presented controller's frame. And the "best" way to do that, I've found, is to use the presenting/container controller's bounds as a starting point. The presenting/container's frame won't accurately reflect changes in orientation.

As an example in code, from my custom container controller:

- (void)slideToEdit {

  // add edit to container and prep home for removal from container
  [self.home willMoveToParentViewController:nil];
  [self addChildViewController:self.edit];

  // the vital frame setting <- this is the bit that solves the problem
  self.edit.view.frame = self.view.bounds;

  // prep the animation
  __block CGRect frame = self.edit.view.frame;
  frame.origin.x += frame.size.width;
  self.edit.view.frame = frame;

  // animate
  [self transitionFromViewController:self.home toViewController:self.edit
    duration:SLIDE_SPEED options:UIViewAnimationCurveLinear animations:^{

    // slide animation
    frame.origin.x -= frame.size.width;
    self.edit.view.frame = frame;

  } completion:^(BOOL done) {
    [self.home.view removeFromSuperview];

    // finalise container heirarchy
    [self.home removeFromParentViewController];
    [self.edit didMoveToParentViewController:self];
  }];
}

This doesn't feel ideal, in that having to manually modify the frame seems wrong when it could be inferred from the nib + current orientation. But this at least works.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top