Эта проблема
Я заметил странное поведение при представлении UINavigationController
(с уже выдвинутым корневым контроллером представления) с UIViewControllerAnimatedTransitioning
во время телефонного звонка.
- Если строка состояния при вызове включена после отображения контроллера навигации, контроллер навигации сдвигает свой вид вниз, как ожидалось. Но когда вызов завершен, контроллер не переключает свой обзор обратно вверх, оставляя зазор 20p под строкой состояния.
- Если строка состояния при вызове включена до представления контроллера, контроллер вообще не учитывает строку состояния, оставляя 4p из 44p-высокой панели навигации выглядывающими из-под строки состояния 40p. . Когда вызов завершен, контроллер сдвигает свой обзор вниз, чтобы разместить обычную строку состояния 20p.
* примечание: это было протестировано на симуляторе из-за простоты включения / отключения строки состояния во время разговора, но тестеры наблюдали это явление на реальных телефонах.
Мое (частичное) решение
Я обошел проблему, настроив рамку контроллера во время презентации, если строка состояния была ненормальной высоты:
@interface CustomAnimationController : NSObject <UIViewControllerAnimatedTransitioning>
@end
@implementation CustomAnimationController
- (void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext
{
UIViewController *toController = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
UIView *container = [transitionContext containerView];
CGRect frame = [transitionContext finalFrameForViewController:toController];
if (CGRectEqualToRect(frame, CGRectZero))
{
// In my experience, the final frame is always a zero rect, so this is always hit
UIEdgeInsets insets = UIEdgeInsetsZero;
// My "solution" was to inset the container frame by the difference between the
// actual status bar height and the normal status bar height
insets.top = CGRectGetHeight([UIApplication sharedApplication].statusBarFrame) - 20;
frame = UIEdgeInsetsInsetRect(container.bounds, insets);
}
toController.view.frame = frame;
[container addSubview:toController.view];
// Perform whiz-bang animation here
}
@end
Это решение гарантирует, что панель навигации находится под строкой состояния, но контроллер навигации по-прежнему не может сдвинуться обратно после завершения вызова. Таким образом, приложение, по крайней мере, можно использовать, но после завершения вызова над панелью навигации появляется уродливый зазор в 20 пикселей.
Есть ли способ лучше?
Я пропустил какой-то важный шаг, чтобы убедиться, что контроллер навигации самостоятельно учитывает строку состояния во время разговора? Он отлично работает, когда представлен встроенным модальным стилем представления.
На мой взгляд, это попахивает ошибкой UIKit - в конце концов, кажется, что контроллер навигации получает UIApplicationWillChangeStatusBarFrameNotification
(см. Второй пункт проблемы). Если кто-то еще столкнулся с этой проблемой и нашел лучший способ, я был бы очень признателен за решение.