Приложение UIScreenFrame возвращает неправильный прямоугольник при запуске приложения с горизонтальной ориентацией (iPhone / iPad)

Возникли проблемы с получением правильных границ для моего приложения iPad при его запуске в альбомном режиме. У меня есть правильные ключи, установленные в моем файле Info.plist, и мои контроллеры представления правильно запускаются в альбомной (и портретной, natch).

В моем методе applicationDidFinishLaunching: я вызываю селектор после 3-секундной задержки, и этот метод вызывает [[UIScreen mainScreen] applicationFrame], но возвращает мне рамку портрета (т.е. высота> ширина).

Кто-нибудь знает, как это исправить? Для меня это пахнет ошибкой (если да, я запрошу радар), но если это предполагаемое поведение, где оно задокументировано?


person jbrennan    schedule 19.04.2010    source источник
comment
Могу я теперь просто сказать «неправильный угол»?   -  person jbrennan    schedule 19.04.2010


Ответы (7)


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

person progrmr    schedule 19.04.2010
comment
Итак, после того, как сообщение будет отправлено контроллеру представления для поворота, будет ли система координат отражать новую ориентацию? Например, после отправки сообщения ширина ›высота? - person Adam Ritenauer; 04.11.2011

Я никогда не полагаюсь на [[UIScreen mainScreen] applicationFrame], особенно при запуске приложения.

При создании представлений в коде используйте супервизор для установки фрейма.

Если вы используете xib-файлы с «смоделированными элементами интерфейса», они будут иметь правильный размер, и все будет отлично работать.

Приложения на основе UINavigationController

В случае приложения на основе UINavigationController захватите фрейм прямо из self.navigationController.view, не пытайтесь использовать [self loadView] и self.view.superview. UINavigationController использует «скрытые» подпредставления для выполнения своей работы, поэтому прямой супервизор не будет работать.

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

Почему не UIScreen

[[UIScreen mainScreen] applicationFrame] работает ненадежно (особенно при запуске приложения в альбомной ориентации). Мой опыт показывает, что свойство interfaceOrientation контроллера просмотра не будет соответствовать ориентации applicationFrame.

person bentford    schedule 29.10.2010
comment
Это так важно! Спасибо - person coco; 27.06.2012
comment
Это очень полезно! Если бы я нашел его раньше, я бы сэкономил много времени! Спасибо! - person coder284; 20.03.2014

Вот так я получаю правильный CGRect, когда контроллер представления находится в альбомной ориентации:

CGRect landscapeBounds;
if (self.view.frame.size.width < self.view.frame.size.height)
    landscapeBounds = CGRectMake(self.view.frame.origin.y, self.view.frame.origin.x, self.view.frame.size.height, self.view.frame.size.width);
else
    landscapeBounds = CGRectMake(self.view.frame.origin.x, self.view.frame.origin.y, self.view.frame.size.width, self.view.frame.size.height);
person Francesco Puglisi    schedule 31.01.2012

Это как задумано. Вам следует запросить размер вашего супервизора и при необходимости изменить его.

person rpetrich    schedule 19.04.2010
comment
Не могли бы вы объяснить, почему это так устроено (или хотя бы предположить). Мне кажется нелогичным давать неверные границы экрана, если он был повернут. Рассматриваемый superview - это окно моего приложения (и я также пробовал использовать его фрейм для тех же результатов). - person jbrennan; 19.04.2010
comment
Причина в том, что окна можно поворачивать независимо от экрана. Пример: когда приложение с вертикальной ориентацией запускает видео YouTube, главное окно остается портретным, но поверх него анимируется горизонтальное окно. Во время анимации следует ли считать устройство портретным или альбомным? (ориентация акселерометра отделена от ориентации окна, отделена от ориентации строки состояния) - person rpetrich; 19.04.2010
comment
Я тоже это заметил, это действительно странно. Спасибо за внимание. - person Justin; 19.04.2010
comment
В этом случае окно моего приложения является моим супервизором, и оно сообщает о границах портретной ориентации, хотя оно и является альбомным. Раздражающий. Но мне просто нужно использовать [UIDevice orientation], чтобы поменять местами w + h, если это необходимо. - person jbrennan; 19.04.2010
comment
-[UIDevice orientation] не следует использовать для этой цели; Вместо этого следует использовать -[UIApplication statusBarOrientation]. UIDeviceOrientation имеет дополнительные состояния, которые в данном случае не имеют смысла: UIDeviceOrientationUnknown, UIDeviceOrientationFaceUp и UIDeviceOrientationFaceDown. - person rpetrich; 20.04.2010

[[UIScreen mainScreen] applicationFrame] всегда будет возвращать портретный прямоугольник, даже если приложение находится в альбомном режиме. Это связано с тем, что UIWindow никогда на самом деле не вращается, а вместо этого просто изменяет преобразование rootViewController.view.

Чтобы убедиться, вы можете распечатать объект корневого представления в портретном и ландшафтном режимах, и вы увидите что-то вроде этого:

Портрет:

<UIView: 0x96290e0; frame = (0 20; 768 1004); ...

Пейзаж:

<UIView: 0x96290e0; frame = (0 20; 768 1004); transform = [0, 1, -1, 0, 0, 0]; ...
person Hejazi    schedule 15.06.2013

Итак, добавьте изображение запуска и дайте ему суффикс -568h, согласно руководствам Apple.

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

Вот место, которое меня научило после быстрого поиска. Я не видел этого ответа выше, подумал, что он будет кому-то полезен.

S

person Stephen J    schedule 15.06.2013

У меня возникла такая же проблема, когда я отклонил представление с помощью dismissViewControllerAnimated в плагине Cordova. Я изменил код singingAtom для метода viewWillAppear в MainViewController, размер которого был изменен после закрытия модального представления:

- (void)viewWillAppear:(BOOL)animated
    {
    CGRect appFrame = [[UIScreen mainScreen] applicationFrame];
    UIDeviceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation];
    if (UIDeviceOrientationLandscapeLeft == orientation || 
        UIDeviceOrientationLandscapeRight == orientation)
            {
            if (appFrame.size.width < appFrame.size.height)
                {
                appFrame = CGRectMake(appFrame.origin.y, appFrame.origin.x, appFrame.size.height, appFrame.size.width);
                }
        }
    self.view.frame = appFrame;
    [super viewWillAppear:animated];
}
person lietus    schedule 11.10.2012