Вопрос

ОБНОВЛЯТЬ:Сначала посмотрите мой ответ на этот вопрос.Похоже, это ошибка.Был создан минимальный тестовый пример и отправлен отчет в Apple.(Исправлено начиная с iPhone OS 3.1.)

Вот головоломка из "Я так близко!" отделение.

У меня есть приложение для iPhone на основе панели вкладок.На каждой вкладке имеется УИНавигационконтроллер с обычными подозреваемыми (панель навигации, просмотр таблицы...что в свою очередь может привести к еще одному ВК и т.д.).

Теперь один из этих VC нижнего уровня будет использоваться в портировании. и Ландшафтные режимы.Но есть проблема.Наши венчурные капиталисты, заботящиеся о ландшафте mustAutorotateToInterfaceOrientation: не будет вызван из коробки!Что делать?

Вот что мы делаем.В моем контроллере панели вкладок, который я реализовал в отдельном файле, у меня есть это:

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
     return [self.selectedViewController shouldAutorotateToInterfaceOrientation:interfaceOrientation];
}

В конечном итоге запрос передается на мой ландшафтный виртуальный компьютер, который также отвечает на это сообщение.Все остальные мои виртуальные компьютеры не реализуют этот метод, поэтому они просто используют портретную ориентацию по умолчанию.

Задача решена!!!Ура!

Хорошо, не совсем. :(

Похоже, дела идут не так хорошо, когда мой ландшафтный виртуальный компьютер вызывается из глубин контроллера панели вкладок. ПодробнееNavigationController.

Я решил сравнить/сопоставить VC, вызванный из одного из первые четыре панель вкладок UINavigationControllers ...и тот самый ВК позвонил изнутри ПодробнееNavigationController.Это будет немного сверхдетально, так что потерпите.Надеюсь, игра за игрой окажется полезной для выяснения обстоятельств.

Когда приложение загружается, происходит несколько первоначальных вызовов метода mustAutorotate... контроллера панели вкладок.метод.В этих ранних случаях выбранныйвиевконтроллер равен нулю.Однако в конце концов мы завершаем загрузку, выбран начальный элемент вкладки, и все в порядке.

Верно.Во-первых, давайте выберем один из первых четырех элементов панели вкладок и перейдем к нашему виртуальному интерфейсу.

Мы выберем третий элемент навигационной панели, то есть это будет третий навигационный контроллер.Мы переходим к нашему VC, который поддерживает ротацию.Быстрая проверка подтверждает, что родительский элемент действительно является третьим навигационным контроллером из списка контроллеров представления нашей панели вкладок.Хороший!

Давайте повернем устройство.Контроллеру панели вкладок предлагается выполнить автоповорот (см. код выше).Мы наблюдаем, что выбранныйвиевконтроллер это также третий навигационный контроллер, плюс контроллеры верхнего и видимого представления навигационного контроллера настроены на наш надежный виртуальный виртуальный контроллер, который поддерживает вращение.

Таким образом, контроллер панели вкладок будет пересылать следуетавтоповорот сообщение третьему навигационному контроллеру...но наш дружелюбный к ротации венчурный инвестор в конечном итоге получает сообщение.(Я не делаю здесь ничего особенного.Может быть, нужный ВК получит сообщение, потому что это верхний и/или видимый ВК?) В любом случае мы поворачиваемся в альбомную ориентацию, размеры элементов изменяются, и все в порядке."Большой успех!"

Теперь давайте нажмем кнопку «Назад» и выдвинем стек VC, оставив при этом альбомный режим.Контроллер панели вкладок запрашивается снова.

Здесь пора немного отступить.А топвиевконтроллер для нашего навигационного контроллера по-прежнему остается удобным для вращения VC, но видимыйвиевконтроллер теперь установлено на UISnapshotModalViewController!Хех.Никогда раньше не видел такого...но Эрика Садун.Похоже, это для «исчезновения контроллеров представления» (что в данном случае, безусловно, верно — все в порядке).

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

Так это сценарий, в котором все работает хорошо.

Теперь давайте попробуем тот же тест, только на этот раз мы отправимся в ПодробнееNavigationController (элемент панели вкладок «Дополнительно») и перейдите к тому же классу VC, что и раньше.В моем случае это седьмой в списке VC контроллера панели вкладок.

Входим в ВК, поддерживающий ротацию, и...на этот раз его просят повернуть напрямую!Контроллер панели вкладок нет попросил разрешения на ротацию вообще.Хм.

Быстрая проверка родительского VC показывает, что это ПодробнееNavigationController.Хорошо, это имеет смысл.

Теперь попробуем повернуть устройство. НИЧЕГО НЕ ВЫЗОВАЕТСЯ.Ни одна из наших точек останова не будет достигнута.Не в нашем ВК.Не в нашем контроллере панели вкладок.(Хм?!?!)

О-каааай.Давайте вытолкнем стек, вернемся в тот же VC и попробуем еще раз повернуть.Странный.СЕЙЧАС мы получаем вызов в контроллере панели вкладок с просьбой разрешить авторотацию.Здесь выбранный контроллер — это наш верный контроллер навигации (#7), но на этот раз видимыйвиевконтроллер и топвиевконтроллер являются УСТАНОВИТЬ НА НОЛЬ!

Как только мы продолжим отсюда, в консоли отладчика появится загадочное сообщение:

Использование двухэтапной анимации вращения.Чтобы использовать более плавную одноэтапную анимацию, это приложение должно удалить двухэтапные реализации метода.

Загадочный, потому что Я не использую двухэтапную анимацию вращения.!Нет Вторая половина варианты метода используются в любом месте моего исходного кода.

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

На этом этапе мы даже не будем утруждать себя извлечением стека.

Я думаю, что документ View Controller намекает на возможную проблему:

Если вы хотите выполнить пользовательские анимации во время изменения ориентации, вы можете сделать это одним из двух способов.Изменения ориентации, используемые для двух шагов, при этом уведомления происходят в начале, среднем и конечной точках вращения.Однако в iPhone OS 3.0 была добавлена ​​поддержка для выполнения изменений ориентации за один шаг.Использование одноэтапного изменения ориентации имеет тенденцию быть быстрее, чем более старый двухэтапный процесс и обычно рекомендуется для любого нового кода.

Интересно, если ПодробнееNavigationController все еще реагирует на двухэтапный процесс и, таким образом, препятствует любым попыткам использовать одноэтапный процесс?Обратите внимание: если вы ответите на двухэтапные сообщения, одноэтапный вариант не будет работать (опять же, согласно документации).Я не отвечаю на них, но у меня есть смутное подозрение, что что-то за кулисами ЕСТЬ.

Фактически, если я закомментирую одношаговый метод и попытаюсь ответить на willAnimateSecondHalfOfRotationFromInterfaceOrientation:duration:, я делать возьми памятку!Но он по-прежнему не очень четко выделяется из стека (с точки зрения визуальных эффектов).Еще более странный: willAnimateFirstHalfOfRotationFromInterfaceOrientation:duration: НЕ вызывается, даже когда я пытался незаметно позвонить самому себе (используя сообщение FirstHalf) в mustAutorotateToInterfaceOrientation:.Он возвращается сразу во время трассировки, как будто я его даже не определял.Вздох.

Итак, это игра за игрой.

Таким образом, имеет любой успешно обработал одношаговую ротацию устройства для VC, вызванного из MoreNavigationController контроллера панели вкладок?Пытливые умы хотят знать!

Это было полезно?

Решение

Apple не советует создавать подклассы UITabBarController, поэтому я нашел простой способ реализовать авторотацию, используя вместо этого категории.Это не исправит вашу ошибку с помощью Подробнее...view, но я думаю, что это более удобный для Apple способ выполнения работы (и означает меньшее количество подклассов для вас).

Чтобы каждая вкладка в моем приложении автоматически поворачивалась, я определил -shouldAutorotateToInterfaceOrientation:в моих пользовательских контроллерах представления, но все они находятся внутри UINavigationControllers внутри UITabBarController, поэтому сообщение не будет отправлено по цепочке в мой VC, пока эти двое также не ответят.Поэтому я добавил следующие строки в файлы делегатов моего приложения:

Добавлено в конец MyAppDelegate.h.

@interface UITabBarController (MyApp)
@end

@interface UINavigationController (MyApp)
@end

Добавлено в конец MyAppDelegate.m.

@implementation UITabBarController (MyApp) 
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation {
    return YES;
}
@end

@implementation UINavigationController (MyApp) 
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation {
    return YES;
}
@end

Другие советы

Похоже, у нас есть ошибка.Я создал воспроизводимый минимальный тестовый пример и сообщил о нем через Apple Bug Reporter (Проблема с радаром 7139857).

Обновлять:Это исправлено в iPhone OS 3.1.

Существенная проблема заключается в следующем:

Просмотр контроллеров уже в стеке навигационных контроллеров не получает willAnimateRotationToInterfaceOrientation:продолжительность:Сообщения, когда используется «больше навигационного контроллера» контроллера стержня.

Эта проблема делает нет происходят, когда контроллеры представления элемента панели вкладок являются базовыми контроллерами представления.Только если они являются навигационными контроллерами и только когда используется иерархия навигации «Дополнительно».

Сообщение консоли (относительно двухэтапной анимации вращения) предполагает, что что-то в рамках (Контроллер дополнительной навигации?) по-прежнему использует двухэтапную анимацию, хотя теперь, начиная с iPhone OS 3.0, рекомендуется использовать одноэтапную анимацию.

Это могло бы объяснить, почему willAnimateRotationToInterfaceOrientation: не вызывается в данном конкретном случае.Согласно документации контроллера представления Apple, это сообщение НЕ будет вызываться, когда вместо этого отвечают на двухэтапные сообщения ориентации первой/второй половины.

Немного модифицированная версия Ответ Викторба что позволяет каждому контроллеру представления решать, разрешает ли он вращение.

Вот суть для упрощения копирования и разветвления.

AppDelegate.h

@interface UITabBarController (MyApp)
@end

@interface UINavigationController (MyApp)
@end

AppDelegate.m

@implementation UITabBarController (MyApp) 
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation {
    UIViewController *selectedVC = [self selectedViewController];
    if ([selectedVC respondsToSelector:@selector(shouldAutorotateToInterfaceOrientation:)]) {
        return [selectedVC shouldAutorotateToInterfaceOrientation:toInterfaceOrientation];
    }

    //optimistic return - if you want no rotation, you have to specifically tell me!
    return YES;
}
@end

@implementation UINavigationController (MyApp) 
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation {
    UIViewController *visibleVC = [self visibleViewController];
    if ([visibleVC respondsToSelector:@selector(shouldAutorotateToInterfaceOrientation:)]) {
        return [visibleVC shouldAutorotateToInterfaceOrientation:toInterfaceOrientation];
    }

    //optimistic return - if you want no rotation, you have to specifically tell me!
    return YES;
}
@end
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top