Я искал долго и упорно, пытаясь понять это. Прошло около 4-5 часов, прежде чем мне наконец удалось найти решение. Я отвечу на свой вопрос, чтобы оказать поддержку любому, кто столкнется с той же проблемой.
Итак, я создал приложение Critical Mass Typer. Это игра на машинке, использующая клавиатуру в качестве основного метода управления. Слова движутся к центру экрана, где у вас есть ядро. Вы вводите слово и уносите слово, прежде чем оно достигнет вашего ядра. Если в ваше ядро попадет 4 слова, вы достигнете критической массы и взорвитесь (игра окончена).
Теперь я хотел иметь возможность поддерживать как альбомный, так и портретный режим в игре. Я думал об этом заранее и разработал свои классы так, чтобы их было легко реализовать. Настройка игры для этого не была проблемой. Правильное вращение видов было.
Одна вещь, которая возникла довольно быстро, заключалась в том, что любое представление, которое возвращает NO для метода shouldAutorotateToInterfaceOrientation контроллера представления, отменяет возврат его подпредставлений.
Итак, мой главный контроллер вида (CriticalMassViewController) управляет запуском / меню игры и добавляет в качестве подпредставления контроллер вида, который запускает игровой режим (CMGameViewController). Я только хочу, чтобы мой основной контроллер вида находился в ландшафтном режиме, потому что, если я поверну его, анимация / кнопки будут все сбоку. Мне бы пришлось создать другой вид или изменить положение всего на экране, если бы я хотел, чтобы он был настроен на портретный режим. Тем не менее, мой взгляд на игру должен иметь возможность переключаться. Для этого вы устанавливаете возвращаемое значение в конкретный режим, которым вы хотите, чтобы ваш основной вид был. Затем сообщите вашему игровому виду, чтобы не возвращался режим. После этого зарегистрируйте игровой вид для уведомлений, а затем самостоятельно выполните поворот.
Например:
CriticalMassViewController.m:
-(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
// Return YES for supported orientations
return (interfaceOrientation == UIInterfaceOrientationLandscapeRight);
}
CMGameViewController.m
- (void)viewDidLoad {
[super viewDidLoad];
/*GUI setup code was here*/
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didRotate:) name:UIDeviceOrientationDidChangeNotification object:nil];
}
-(void)didRotate:(NSNotification *)nsn_notification {
UIInterfaceOrientation interfaceOrientation = [[UIDevice currentDevice] orientation];
/*Rotation Code
if(interfaceOrientation == UIInterfaceOrientationPortrait) {
//Portrait setup
} else if(interfaceOrientation == UIInterfaceOrientationLandscapeRight) {
//Landscape setup
}
*/
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
// Return YES for supported orientations
return NO;
}
Хорошо, так что здесь происходит? Мой основной контроллер вида хочет быть только в режиме LandscapeRight. Таким образом, он остается таким, поскольку он никогда не регистрируется для любой другой ориентации для автоматического поворота. Мой игровой контроллер должен вращаться. Если я использую следующий код для shouldAutorotateToInterfaceOrientation
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
return (interfaceOrientation == UIInterfaceOrientationPortrait || interfaceOrientation == UIInterfaceOrientationLandscapeRight);
}
ЭТО НЕ БУДЕТ ВРАЩАТЬ, КОГДА IPHONE ИЗМЕНИТ ОРИЕНТАЦИЮ. Это потому, что его супер вид говорит, что он не хочет вращаться. Как только суперпредставление возвращает «нет», подпредставление даже не запрашивается. Таким образом, вместо этого мы, контроллер игровых представлений, просто говорим «Нет», я не хочу автоматически поворачиваться к любому представлению. Затем мы регистрируемся для уведомления об изменении ориентации и вызываем наш собственный метод поворота.
Эти последние биты кода - это то, как вы сами управляете вращением. Вызовите rotateView изнутри didRotate. Обратите внимание, я хочу, чтобы пользователь мог поворачиваться только после выбора сложности, поэтому у меня есть логика внутри моего метода didRotate, чтобы определить, должен ли он вообще вращаться. Комментарии в коде объяснят, почему происходят определенные вещи.
-(void) rotateView:(UIInterfaceOrientation)uiio_orientation {
/*This line is very important if you are using the keyboard. This was actually the
largest problem I had during this entire ordeal. If you switch orientations while
the keyboard is already being displayed, it will stay in landscape orientation. To
get it to switch to portrait, we have to tell the status bar that its orientation
has changed. Once you do this, the keyboard switches to portrait*/
[UIApplication sharedApplication].statusBarOrientation = uiio_orientation;
//Get the view you need to rotate
UIView *portraitImageView = self.view;
/*Check to make sure that you are in an orientation that you want to adjust to. If
you don't check, you can make your view accidently rotate when the user orientates
their phone to a position you aren't expecting*/
if(uiio_orientation == UIInterfaceOrientationPortrait || uiio_orientation == UIInterfaceOrientationLandscapeRight) {
if(uiio_orientation == UIInterfaceOrientationPortrait) {
//This transform rotates the view 90 degrees counter clock wise.
portraitImageView.transform = CGAffineTransformMakeRotation(-M_PI/2);
} else if(uiio_orientation == UIInterfaceOrientationLandscapeRight) {
//This transform rotates the view back to its original position
portraitImageView.transform = CGAffineTransformMakeRotation(0);
}
CGRect frame = portraitImageView.frame;
frame.origin.y = 0;
frame.origin.x = 0;
frame.size.width = portraitImageView.frame.size.height;
frame.size.height = portraitImageView.frame.size.width;
portraitImageView.frame = frame;
}
}
Надеюсь, это кому-нибудь поможет, я знаю, что мне было очень тяжело, особенно когда клавиатура переключалась с пейзажа на портрет.