iOS5 прерывает обратные вызовы вращения UISplitViewController, как вызывать вручную?

Как сообщалось в других вопросах здесь, на SO, iOS 5 меняет способ обратного вызова вращения для контроллеров разделения представления отправлено в соответствии с этим примечанием к выпуску. Это не обман (я думаю), так как я не могу найти другого вопроса по SO, который касается того, как настроить использование контроллера разделения представления в iOS 5, чтобы справиться с изменением:

Обратные вызовы вращения в iOS 5 не применяются для просмотра контроллеров, которые представлены в полноэкранном режиме. Это означает, что если ваш код представляет контроллер представления над другим контроллером представления, а затем пользователь впоследствии поворачивает устройство в другую ориентацию, после увольнения, лежащий в основе контроллер (то есть представляющий контроллер) не получит никаких обратных вызовов ротации. Однако обратите внимание, что представляющий контроллер получит вызов viewWillLayoutSubviews при его повторном отображении, а свойство interfaceOrientation можно запросить из этого метода и использовать для правильной компоновки контроллера.

У меня возникли проблемы с настройкой кнопки всплывающего окна в моем корневом контроллере разделенного представления (тот, который должен отображать вид левой панели во всплывающем окне, когда вы находитесь в портретной ориентации). Вот как моя последовательность запуска приложения работала в iOS 4.x, когда устройство находится в альбомном режиме:

  1. Установите контроллер разделения представления в окно с помощью [window addSubview: splitViewController.view]; [окно makeKeyAndVisible]; . Это приводит к тому, что splitViewController: willHideViewController: withBarButtonItem: forPopoverController: вызывается для делегата (т. Е. Имитирует горизонтальный -> портретный поворот), даже если устройство уже находится в ландшафтном режиме.

  2. Представьте полноэкранный модальный экран (мой экран загрузки), который полностью покрывает разделенное изображение внизу.

  3. Завершите загрузку и закройте модальный экран загрузки. Поскольку устройство находится в ландшафтном режиме, когда открывается контроллер разделения представления, это вызывает вызов splitViewController: willShowViewController: invalidatingBarButtonItem: для делегата (т. Е. Имитация портретного -> горизонтального вращения), что делает недействительным bar, удалив его с правой стороны разделенного представления и оставив нас там, где мы хотим быть. Ура!

Итак, проблема в том, что из-за изменения, описанного в этом примечании к выпуску, все, что происходит внутри iOS 4.3, в результате чего вызывается splitViewController: willShowViewController: invalidatingBarButtonItem: больше не вызывается в iOS 5. I попытался создать подкласс UISplitViewController, чтобы я мог предоставить настраиваемую реализацию viewWillLayoutSubviews , как было предложено в примечании к выпуску, но я не знаю, как воспроизвести желаемую последовательность внутренних событий, запускаемых iOS 4. Я пробовал это:

- (void) viewWillLayoutSubviews
{
    [super viewWillLayoutSubviews];

    UINavigationController *rightStack = [[self viewControllers] objectAtIndex:1];
    UIViewController *rightRoot = [[rightStack viewControllers] objectAtIndex:0];
    BOOL rightRootHasButton = ... // determine if bar button item for portrait mode is there

    // iOS 4 never goes inside this 'if' branch
    if (UIInterfaceOrientationIsLandscape( [self interfaceOrientation] ) &&
        rightRootHasButton)
    {
        // Manually invoke the delegate method to hide the popover bar button item
        [self.delegate splitViewController:self
                    willShowViewController:[[self viewControllers] objectAtIndex:0]
                 invalidatingBarButtonItem:rightRoot.navigationItem.leftBarButtonItem];
    }
}

В основном это работает, но не на 100%.Проблема в том, что самостоятельный вызов метода делегата не на самом деле делает недействительным элемент кнопки панели, поэтому при первом повороте в портретную ориентацию система считает, что элемент кнопки панели все еще установлен правильно, и не пытается переустановить. Только после того, как вы снова повернетесь в альбомную, а затем обратно в портретную, система вернется в правильное состояние и фактически установит элемент кнопки всплывающей панели в портретном режиме.

Основываясь на этом вопросе , я также попытался вызвать все обратные вызовы вращения вручную вместо запуска метода делегата, например:

// iOS 4 never goes inside this 'if' branch
if (UIInterfaceOrientationIsLandscape( [self interfaceOrientation] ) &&
    rightRootHasButton)
{
    [self willRotateToInterfaceOrientation:self.interfaceOrientation duration:0];
    [self willAnimateRotationToInterfaceOrientation:self.interfaceOrientation duration:0];
    [self didRotateFromInterfaceOrientation:self.interfaceOrientation];
}

Однако это просто вызывает бесконечный цикл обратно в viewWillLayoutSubviews : (

Кто-нибудь знает, какой правильный способ имитировать события вращения в стиле iOS4 для контроллера с разделенным представлением, который появляется из-за полноэкранного модального окна? Или вы не должны имитировать их вообще, и есть ли еще один передовой подход, который стал стандартом для iOS5?

Любая помощь действительно ценится, поскольку эта проблема удерживает нас от отправки нашего выпуска исправлений iOS5 в App Store.

12
задан Community 23 May 2017 в 12:24
поделиться