UIViewController вращать методы - PullRequest
17 голосов
/ 14 февраля 2009

Какой объект отвечает за передачу вызовов метода вращения UIViewController, т. Е.

  • shouldAutorotateToInterfaceOrientation:
  • willRotateToInterfaceOrientation:duration:
  • willAnimateFirstHalfOfRotationToInterfaceOrientation:duration:
  • willAnimateSecondHalfOfRotationFromInterfaceOrientation:duration:
  • didRotateFromInterfaceOrientation:

Я предполагаю, что это UIApplication (но, может быть, AppDelegate или UIWindow).

Следующий вопрос: откуда объект узнает, с кем UIViewController разговаривать?

Как он узнает, какой UIViewController имеет свой вид как подпредставление окна?

Есть ли сообщение, которое вы можете отправить, или свойство, которое вы можете установить (для какого-либо объекта), которое устанавливает "Active" UIViewController для приложения?

Ответы [ 4 ]

13 голосов
/ 19 февраля 2009

Похоже, что UIApplication отправляет сообщение активному контроллеру представления.

Но как ваш экземпляр View Controller получает эти сообщения?

Сообщение пересылается первому контроллеру представления, чье представление было добавлено к экземпляру UIWindow.

Это сводится к 3 основным сценариям:

  1. ViewController, вид которого добавлено непосредственно к UIWindow экземпляр (приложение с одним представлением)

  2. Контроллер навигации в Приложение на основе навигации, затем навигационный контроллер пересылает сообщение для просмотра активных просмотров контроллер.

  3. Панель вкладок Контроллер в панели вкладок приложение, затем панель вкладок контроллер пересылает сообщение контроллер представления активных представлений (или активный навигационный контроллер).

Проблема, с которой вы столкнетесь, заключается в том, что вы создаете приложение с несколькими представлениями, но НЕ используете контроллер навигации или контроллер панели вкладок. Если вы меняете представления в / из экземпляра UIWindow вручную, вы не будете получать эти сообщения надежно. Это похоже на посты, подобные этой: iPhone viewWillAppear не стреляет

Просто используйте соглашения Apple для нескольких просмотров, и все будет в порядке. Надеюсь, это сэкономит примерно час или два

4 голосов
/ 06 мая 2009

Как он узнает, какой UIViewController имеет свое представление как подпредставление окна?

Класс UIViewController поддерживает статическую карту между представлениями и их контроллерами представления. Эта карта запрашивается в нескольких ключевых местах внутри CocoaTouch. В частности, [UIView nextResponder] запрашивает его и возвращает контроллер, если найден.

Полагаю, UIWindow выполняет тот же поиск в своем корневом представлении, чтобы узнать, какому контроллеру пересылать события вращения. Проверим это в следующий раз, я что-нибудь найду в разборке. (Я потратил некоторое время на обратное проектирование CocoaTouch, чтобы понять, как там все работает.)

4 голосов
/ 14 февраля 2009

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

(Но если вы поэкспериментируете с отладчиком, вы можете прийти к тому же выводу, который у меня есть: есть какая-то внутренняя таблица, отображающая представление каждого контроллера обратно в контроллер, и сообщения отправляются на основе этой ссылки.)


Обновление: Это было по-настоящему приватное волшебство в 2009 году, когда я впервые написал этот ответ, но последующие изменения в iOS сделали открытыми его API-интерфейсы. Корневой контроллер представления теперь доступен через свойство UIWindow.rootViewController, а дерево контроллеров дочернего представления формируется с использованием свойства UIViewController.childViewControllers.

Родительские контроллеры представления отвечают за уведомление своих детей об изменениях ориентации. (Я не уверен, как контроллер корневого представления уведомляется, но вы можете установить точку останова и узнать сами.) Метод -shouldAutomaticallyForwardRotationMethods решает, сделает ли UIViewController это за вас. Если он возвращает NO, вы становитесь ответственным за это в ваших -willRotateToInterfaceOrientation:duration:, -willAnimateRotationToInterfaceOrientation:duration: и -didRotateFromInterfaceOrientation: методах.

1 голос
/ 25 марта 2010

У меня похожая проблема.

У меня есть игра, работающая в альбомной ориентации (как левая, так и правая).

Для управления приложением с несколькими представлениями я использую корневой UIviewController, то есть фиктивный UIViewcontroller с UIview, который ничего не делает. Затем я добавляю в него каждое другое UIview как подпредставление.

При запуске приложения эмулятор быстро поворачивается в портретную ориентацию, и я получаю каждый из моих видов со свойством frame, похожим на (0, -80 320,480). Это приводит к тому, что вид обрезается прямоугольником 160 X 320 с правой стороны.

Я заметил, что - shouldAutorotateToInterfaceOrientation: метод каждого подпредставления вызывается только один раз, и это происходит, когда он добавляется в корневое представление. Позже, при повороте устройства, только корневой вид получает его метод.

Неудивительно, что любой из вызовов методов - willAnimate * отправляется только в корневое представление, поэтому определение любого из этих методов в подпредставлениях бессмысленно.

Эти методы вызываются каждый раз, когда ориентация изменяется на ориентацию, принятую методом - shouldAutorotateToInterfaceOrientation:. поэтому я решил, что могу изменить свойство frame моих подпредставлений оттуда.

Для этого я определил следующий метод в своем классе rootViewController:

- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation duration:(NSTimeInterval)duration
{
    subview1_ViewController.view.frame = CGRectMake(0,0,480,320);
    subview2_ViewController.view.frame = CGRectMake(0,0,480,320);
        ...
}

Я не понимаю, почему свойство frame не обновляется, но я знаю, что этот обходной путь работает.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...