UIWindow с неправильным размером при использовании ландшафтной ориентации
У меня есть пустое приложение, в котором нет раскадровки или xib. Я хочу иметь скрытую строку состояния и поддерживать только ландшафтную ориентацию. Опять же, я не буду вносить эти изменения только в код и не касаюсь Info.plist.
Проблема
Я создаю UIWindow с контроллером, который говорит, что только поддерживаемая ориентация - это пейзаж. В этом случае мой UIWindow создается в размерном режиме портрета и не вращается. Ожидаемым результатом будет экран, который полностью голубой.
![Broken UIWindow]()
Это мой делегат:
#import "AppDelegate.h"
#import "AppViewController.h"
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
self.window.backgroundColor = [UIColor cyanColor];
self.window.rootViewController = [[AppViewController alloc] init];
[self.window makeKeyAndVisible];
return YES;
}
@end
Это мой контроллер:
#import "AppViewController.h"
@implementation AppViewController
- (BOOL)shouldAutorotate {
return YES;
}
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation {
return UIInterfaceOrientationLandscapeLeft;
}
- (BOOL)prefersStatusBarHidden {
return YES;
}
- (NSUInteger)supportedInterfaceOrientations {
return UIInterfaceOrientationMaskLandscape;
}
@end
То, что я пробовал до сих пор
Если я установил rootViewController после вызова makeKeyAndVisible, все, кажется, работает сначала.
self.window.backgroundColor = [UIColor cyanColor];
[self.window makeKeyAndVisible];
self.window.rootViewController = [[AppViewController alloc] init];
Есть еще некоторые проблемы. Прежде всего мне это не нравится, поскольку он кажется очень хрупким. Вторая проблема заключается в том, что в более сложном приложении, которое устанавливает GLKViewController как rootViewController, я получаю следующий результат (ожидается, что не будет черной области слева):
![Broken GLKViewController]()
Похоже, что строка состояния не скрыта достаточно рано. Несколько распознавателей жестов активны, а в GLKViewController и нажатии на черную область выводится следующее сообщение журнала:
2014-09-25 13: 20: 42.170 StackOverflowExample [6971:107907] неожиданное окно nil в _UIApplicationHandleEventFromQueueEvent, _windowServerHitTestWindow: UIClassicWindow: 0x7fa20b805e00; frame = (0 0; 375 667); userInteractionEnabled = НЕТ; gestureRecognizers = NSArray: 0x7fa20b80a620; layer = UIWindowLayer: 0x7fa20b806890
Я также выполнил различные другие изменения, такие как присоединение пустого UIViewController и добавление моего представления в качестве подзадачи. В этом случае мое представление выглядит корректно, но окно по-прежнему использует неправильные размеры.
Все вращается правильно, если я не переопределяю методы supportedInterfaceOrientations в моем контроллере представления. Но это, конечно, не то, что я хочу.
Ответы
Ответ 1
При запуске приложения ландшафт из режима портрет UIScreen имеет ограничения портрет в iOS 8 (только если у вас нет этого приложения в приложении панель управления, так как iOS 8 создает некоторый кеш). Даже отображение окна с makeKeyAndVisible
не изменяет его. Но он меняет [UIScreen mainScreen].bounds
согласно AppViewController
доступной ориентации.
#import "AppDelegate.h"
#import "AppViewController.h"
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Portrait bounds at this point
self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
self.window.backgroundColor = [UIColor cyanColor];
self.window.rootViewController = [[AppViewController alloc] init];
[self.window makeKeyAndVisible];
return YES;
}
@end
Итак, давайте изменим рамку окна после [self.window makeKeyAndVisible]
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
self.window = [UIWindow new];
self.window.backgroundColor = [UIColor cyanColor];
self.window.rootViewController = [[AppViewController alloc] init];
[self.window makeKeyAndVisible];
// Here it is
self.window.frame = [UIScreen mainScreen].bounds;
return YES;
}
Я думаю, что это ошибка iOS 8.
Ответ 2
У меня была аналогичная проблема, только для портрета.
Я исправил проблему, установив ориентацию строки состояния перед созданием UIWindow
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// Init my stuff
// ...
// Prepare window
[application setStatusBarOrientation:UIInterfaceOrientationPortrait animated:NO]; // prevent start orientation bug
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
[self.window makeKeyAndVisible];
return YES;
}
В вашем случае вы должны использовать UIInterfaceOrienationLandscapeLeft
(или Right) в методе setStatusBarOrientation:animated:
.
Надеюсь, это поможет вам.
Ответ 3
Лично ни одно из представленных выше решений не работало. Я, наконец, установил "скрытый" в значение YES для окна в моем главном xib, как было предложено здесь: неожиданное окно nil в _UIApplicationHandleEventFromQueueEvent, _windowServerHitTestWindow
Ответ 4
Проблема возникает при добавлении экрана запуска, который вы можете сделать, добавив дополнительное свойство в info.plist
была ли эта проблема сама, я не уверен, что вы можете добавить ее через код, хотя мне удалось заставить ее работать с info.plist + Launch Screen xib file
<key>UILaunchStoryboardName</key>
<string>Launch Screen</string>
На самом деле, я не думаю, что вам нужно добавить xib файл, если только ключ (с любым значением) доступен в plist, он должен работать.
Ответ 5
Ни одно из решений, размещенных здесь или в другом месте, не работало для меня.
Однако я обнаружил, что эта проблема, по-видимому, не встречается в Storyboards, поэтому альтернативным решением является переход от xib. (Этот факт, к сожалению, также маловероятен, что Apple серьезно относится к проблеме.)