there are others that suggest just modifying the view position, but that seems like a tacky hack
No, it's not a tacky hack. That's what you do. A custom transition animation simply means that you are in charge of bringing the new view into the scene - provided it ends up in the right place. So the way to animate it in from the bottom is simply to position it at the bottom and animate it up into place.
So for example (taken almost directly from the example code in my book):
-(void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext {
// boilerplate
UIViewController* vc1 =
[transitionContext
viewControllerForKey:UITransitionContextFromViewControllerKey];
UIViewController* vc2 =
[transitionContext
viewControllerForKey:UITransitionContextToViewControllerKey];
UIView* con = [transitionContext containerView];
CGRect r1start = [transitionContext initialFrameForViewController:vc1];
CGRect r2end = [transitionContext finalFrameForViewController:vc2];
UIView* v1 = vc1.view;
UIView* v2 = vc2.view;
// end boilerplate
CGRect r = r2end;
r.origin.y += r.size.height; // start at the bottom...
v2.frame = r;
[con addSubview:v2];
[[UIApplication sharedApplication] beginIgnoringInteractionEvents];
[UIView animateWithDuration:0.4 animations:^{
v2.frame = r2end; // ... and move up into place
} completion:^(BOOL finished) {
[transitionContext completeTransition:YES];
[[UIApplication sharedApplication] endIgnoringInteractionEvents];
}];
}
That code is adapted from my example at https://github.com/mattneub/Programming-iOS-Book-Examples/blob/master/bk2ch06p292customAnimation1/ch19p620customAnimation1/AppDelegate.m The example is almost exactly what you are describing except it's for a tab controller instead of a navigation controller and it comes in from the side instead of the bottom. But the principle is exactly the same.