"Неверный" размер кадра/окна после переориентации в iPhone

В приложении iPhone OS я хочу (нужно) следить за изменениями в ориентации устройства, чтобы изменить некоторые части экрана. Подход, который я использовал, состоял в том, чтобы использовать CGRect frame = [UIScreen mainScreen].applicationFrame для получения размера экрана, а оттуда вычислять размер и/или позиционирование других элементов управления (я также пробовал self.view.frame).

Все тесты были выполнены до сих пор в режиме портрета, поэтому я мог сосредоточиться на программировании основных функций, а затем просто внести некоторые корректировки для Пейзажа. И здесь возникает проблема: В -(void) didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation я добавил некоторые записи для проверки размеров перед продолжением, но, видимо, значения для Width и Height являются "неправильными" (я говорю "неправильно", потому что на первый взгляд значения не имеют смысла мне).

Здесь вывод некоторого журнала:

  • Поворот: Пейзаж [w = 300.000000, h = 480.000000]
  • Поворот: портрет [w = 320.000000, h = 460.000000]

Значения для "w" и "h" в ландшафте кажутся инвертированными для меня - я ожидал, что w = 480 и h = 300.

Что я делаю неправильно? Код, который я использовал для отладки, приведен ниже.

-(void) didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation {
    CGRect frame = [UIScreen mainScreen].applicationFrame;
    CGSize size = frame.size;

    NSLog(@"%@", [NSString stringWithFormat:@"Rotation: %s [w=%f, h=%f]",  
        UIInterfaceOrientationIsPortrait(self.interfaceOrientation) ? "Portrait" : "Landscape",
        size.width, size.height]);
}

Ответ 1

Ориентация вашего устройства изменилась, а не физические характеристики экрана. Вы в основном набросились на бок, но на самом деле это 320 пикселей в ширину (20 из которых недоступны вам в данный момент, так как отображается строка состояния) и 480 пикселей в высоту. Если ваше изображение автоматически вращается, ширина/высота были переведены для вас, но когда вы запрашиваете фактические размеры экрана, вы возвращаете фактические размеры экрана.

Именно поэтому при работе с переведенными представлениями важно выполнять вычисления на основе центра просмотра и границ представления, а не в рамке представления.

Ответ 2

Используйте self.view.bounds вместо этого.

Ответ 3

Я столкнулся с одной и той же проблемой, и с некоторой диагностической работой я обнаружил, что границы представления и кадр не точно отражают ландшафтную ориентацию в viewDidLoad (когда устройство удерживается в ландшафтном режиме, когда контроллер просмотра нажат в стек), но делайте это правильно в viewWillAppear: и viewDidAppear:. Я просто переместил свой код, который нуждался в размерах рамки/границ от viewDidLoad до viewWillAppear:, и он работал правильно.