Проблема
Я заметил какое-то странное поведение при представлении UINavigationController
(с контроллером корневого представления, который уже был нажат, естественно) с помощью UIViewControllerAnimatedTransitioning
во время телефонного разговора.
- Если строка состояния вызова включена после отображения навигационного контроллера, навигационный контроллер сдвигает свой вид вниз, как ожидалось. Но когда вызов завершен, контроллер не сдвигает свое представление назад, оставляя пробел 20p под строкой состояния.
- Если строка состояния вызова включена, перед представлением контроллера контроллер вообще не учитывает строку состояния, оставляя 4p навигационной панели 44p-high, выглядывающей из-под строки состояния 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
Это решение гарантирует, что навигационная панель находится ниже строки состояния, но навигационный контроллер по-прежнему не может выполнить резервное копирование при завершении вызова. Таким образом, приложение, по крайней мере, можно использовать, но после завершения вызова появляется уродливый 20p-зазор над навигационной панелью.
Есть ли лучший способ?
Неужели я пропустил какой-то важный шаг, чтобы убедиться, что контроллер навигации отвечает за состояние в строке состояния вызова? Он отлично работает, когда представлен встроенный модальный стиль презентации.
По-моему, это приносит ошибку UIKit - в конце концов, навигационный контроллер, похоже, получает UIApplicationWillChangeStatusBarFrameNotification
(см. вторую точку проблемы). Если кто-то еще столкнулся с этой проблемой и нашел лучший способ, я был бы очень признателен за решение.