Подтвердить что ты не робот

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 в моем контроллере представления. Но это, конечно, не то, что я хочу.

4b9b3361

Ответ 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:.

Надеюсь, это поможет вам.

Ответ 4

Проблема возникает при добавлении экрана запуска, который вы можете сделать, добавив дополнительное свойство в info.plist

была ли эта проблема сама, я не уверен, что вы можете добавить ее через код, хотя мне удалось заставить ее работать с info.plist + Launch Screen xib file

<key>UILaunchStoryboardName</key>
<string>Launch Screen</string>

На самом деле, я не думаю, что вам нужно добавить xib файл, если только ключ (с любым значением) доступен в plist, он должен работать.

Ответ 5

Ни одно из решений, размещенных здесь или в другом месте, не работало для меня.

Однако я обнаружил, что эта проблема, по-видимому, не встречается в Storyboards, поэтому альтернативным решением является переход от xib. (Этот факт, к сожалению, также маловероятен, что Apple серьезно относится к проблеме.)