У меня есть приложение для iPhone, большинство из которых только для портрета, но с одним контроллером представления (экран видеоплеера), который должен поддерживать как портрет, так и пейзаж (это только для iOS 8). Чтобы достичь этого, я установил приложение plist для поддержки портрета и обоих видов ландшафта, а затем подкласса UINavigationController
; в этом подклассе я переопределяю
- (BOOL)shouldAutorotate {
return YES;
}
и
- (NSUInteger)supportedInterfaceOrientations {
if ([self.visibleViewController isKindOfClass:[MyVideoPlayerScreen class]]) {
return UIInterfaceOrientationMaskAllButUpsideDown;
} else {
return UIInterfaceOrientationMaskPortrait;
}
}
Это в основном работает так, как ожидалось: начальные экраны - только портретные и остаются в портрете, даже когда устройство повернуто к пейзажу. Видеопроигрыватель при первоначальном представлении:
MyVideoPlayerScreen *newVC = [MyVideoPlayerScreen new];
[self.navigationController pushViewController:newVC animated:YES];
также находится в портрете, но затем поворачивается к пейзажу, когда устройство повернуто - все хорошо до сих пор.
Проблема заключается в том, что если я превращу устройство в альбомное, видеопроигрыватель тоже будет ландшафтным, но затем, когда я уберу экран видеопроигрывателя с помощью кнопки "Назад", основной контроллер представления (который должен быть только портретным ) теперь также в ландшафте. Если я верну устройство обратно к портрету, контроллер просмотра снова вернется к портрету, и затем он будет правильно зафиксирован только в портретном режиме с этой точки.
Как я могу получить исходный контроллер представления (который должен быть только для портрета), чтобы автоматически вернуться к портрету, когда над ним выскочил контроллер ландшафтного вида?
Этот вопрос задан в миллион раз, но, похоже, исправления, которые были отправлены для него, - это все хаки, которые больше не работают в iOS 8.
Обновление: Я нашел исправление типа для этого, которое работает в iOS 8. В моем подклассе UINavigationController
я обрабатываю протокол <UINavigationControllerDelegate>
. Я применил этот метод:
- (void)navigationController:(UINavigationController *)navigationController didShowViewController:(UIViewController *)viewController animated:(BOOL)animated {
if (![viewController isKindOfClass:[MyVideoPlayerScreen class]]) {
// if the current orientation is not already portrait, we need this hack in order to set the root back to portrait
UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation];
if (orientation != UIInterfaceOrientationPortrait) {
// HACK: setting the root view controller to nil and back again "resets" the navigation bar to the correct orientation
UIWindow *window = [[UIApplication sharedApplication] keyWindow];
UIViewController *vc = window.rootViewController;
window.rootViewController = nil;
window.rootViewController = vc;
}
}
}
Это, по крайней мере, оставляет пользовательский интерфейс в состоянии, в котором я хочу, чтобы он находился. Проблема в том, что когда диспетчер представлений верхнего уровня уволен и анимирован за кадром, основной контроллер представления все еще находится в ландшафте; затем он внезапно перескакивает на портрет. Не идеально, но лучше, чем ничего.
Обновление 2: Я должен был добавить, что я нажимаю второй контроллер представлений следующим образом:
ViewControllerPortraitLandscape *newVC = [ViewControllerPortraitLandscape new];
[self.navigationController pushViewController:newVC animated:YES];
Обновление 3: ОК, это вполне выполнимо, что работает для iOS 6 и выше. Исправление даже имеет смысл, хотя причина его работы, похоже, не в документации. В принципе, в контроллере представления вам нужно быть reset на портрете, когда диспетчер представлений верхнего уровня отклоняется, пока устройство по-прежнему находится в ландшафте, вам просто нужно добавить это:
- (NSUInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskPortrait;
}
Хотя мой подкласс UINavigationController
полностью отвечает за вызовы вращения, точки останова показывают, что supportedInterfaceOrientations
вызывается на базовом контроллере представления перед тем, как высший уровень отклоняется, и он вызвал контроллер навигации после верхнего уровня -level отклоняется. Поэтому я предполагаю, что этот вызов самому контроллеру представления сделан iOS, чтобы определить, на какую ориентацию должен находиться основной контроллер представления (и для этого он не запрашивает навигационный контроллер); если он явно не переопределен, он вернет параметр all-but-upside-down, поэтому iOS просто оставляет его там, где он есть, в ландшафте.