WillAnimateRotationToInterfaceOrientation не вызывается для popViewControllerAnimated

В MainViewController мне нужно настроить некоторые изображения при изменении ориентации. Легко - просто добавьте код в willAnimateRotationToInterfaceOrientation: callback

- (void) willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)orientation duration:(NSTimeInterval)duration {
  NSLog(@"orientation: %@", name(orientation));
  ..

Работает так, как ожидалось. В то время как в Portrait я нажимаю на UIViewController с ориентацией на ориентацию UINavigationController. Я вращаюсь в Пейзаж, и все хорошо.

Затем я возвращаюсь к MainViewController, вызывая

[self.navigationController popViewControllerAnimated:YES];

В то время как подпрограммы MainViewController настроены на Landscape в соответствии с масками авторазмера, willAnimateRotationToInterfaceOrientation: не будет вызван!

Я бы ожидал, что willAnimateRotationToInterfaceOrientation: либо вызывается, когда не находится поверх стека контроллера навигации, либо, по крайней мере, вызывается при возврате в верхнюю часть стека.

Я предполагаю, что я мог бы вручную вызвать willAnimateRotationToInterfaceOrientation: перед попсом, но это кажется неправильным.

Что мне не хватает?

Ответ 1

Это ожидаемое поведение, как я вижу. Если UIVC не находится в верхней части стека, тогда willAnimateRotationToInterfaceOrientation не следует вызывать, поскольку в это время анимация не анимация. То, как я занимаюсь этим в приложении, над которым я сейчас работаю, похоже на вышеупомянутый плакат. Любой UIVC, который поддерживает все ориентации, получает новый метод

- (void) updateLayoutForNewOrientation: (UIInterfaceOrientation) orientation;

Этот метод вызывается из двух мест:


-(void) viewWillAppear: (BOOL) animated {
  [super viewWillAppear: animated];
  [self updateLayoutForNewOrientation: self.interfaceOrientation];
}

-(void) willAnimateRotationToInterfaceOrientation: (UIInterfaceOrientation) interfaceOrientation duration: (NSTimeInterval) duration { [self updateLayoutForNewOrientation: interfaceOrientation]; }

Новый метод прост:


- (void) updateLayoutForNewOrientation: (UIInterfaceOrientation) orientation {
    if (UIInterfaceOrientationIsLandscape(orientation)) {
        // Do some stuff
    } else {
        // Do some other stuff
    }
}

Кроме того, если вы беспокоились о том, что код работает, когда он на самом деле не нужен, вы можете отслеживать ориентацию устройства, когда новый UIVC был перенесен в стек через переменную экземпляра, установленную в viewDidDisappear, и проконсультируйтесь с ней, чтобы решить если вы хотите "Делать материал"

Ответ 2

Разве это не правильное поведение? Потому что обратный вызов анимации должен вызываться только до изменения анимированной ориентации. Когда вы открываете верхний вид, вы видите поп-анимацию, а затем уже повернутое изображение под ней. Нет анимации вращения и, следовательно, нет обратного вызова. (Но вы обязательно должны получить willRotateToInterfaceOrientation:duration:.)

P.S. У меня есть образец проекта Xcode для экспериментов по ориентации интерфейса на GitHub, вам может быть интересно.

Ответ 3

так как нет вращения, когда вы вернетесь к основному виду, willAnimateRotationToInterfaceOrientation не будет вызван. Однако, если вы хотите сделать некоторые вещи на основе измененной ориентации, вы можете добавить следующий код в свой метод viewWillAppear главного диспетчера представлений

- (void)viewWillAppear:(BOOL)animated {
UIInterfaceOrientation statusBarOrientation = [[UIApplication sharedApplication] statusBarOrientation];
    if(UIInterfaceOrientationIsPortrait(statusBarOrientation)){
        NSLog(@"Portrait");
....your code....
    }
    else {
        NSLog(@"Landscape");
....your code....
    }


}

Ответ 4

Я с Скоттом на этом - я думаю, что это поведение должно ожидаться.

См. также Руководство по программированию контроллера просмотра, в котором указано, что вызовы будут обрабатываться только у самого первого контроллера. (Найдите "самый передний", чтобы найти два соответствующих места в документе.)

Ответ 5

Я также испытал такое поведение, и я думаю, что это связано с производительностью и архитектурными соображениями; AFAIK этот метод вызывается внутри контекста анимации UIView (который позволяет вам изменять рамки и центры и иметь приятную анимацию, пока все вращается), и когда ваш контроллер просмотра не отображается, либо UIKit избегает выполнения этого метода, либо просто невозможно выполните его, потому что представление не видно (и, вероятно, вы не можете анимировать то, что видите). Опять же, это чистая спекуляция:)