UIViewController旋转方法

什么对象负责对UIViewController旋转方法的调用,即:

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

我想这是UIApplication (但也许是AppDelegate或UIWindow)。

接下来的问题是,对象如何知道要与哪个UIViewController交谈?

它如何知道哪个UIViewController的视图作为窗口的子视图?

有没有一个消息,你可以发送或一个属性,你可以设置(的一些对象),为应用程序设置“活动” UIViewController

看来, UIApplication正在调度一个消息到主动视图控制器。

但是,您的View Controller实例如何获取这些消息?

该消息被转发到其视图已被添加到UIWindow实例的第一个视图控制器。

这归结为3个基本情况:

  1. 其视图直接添加到UIWindow实例的ViewController(单视图应用程序)

  2. 导航控制器在基于导航的应用程序中,然后导航控制器将消息转发到活动视图视图控制器。

  3. 在基于标签栏的应用程序中的标签栏控制器,然后标签栏控制器将消息转发给活动视图视图控制器(或活动导航控制器)。

您将遇到的问题是,如果您使用多个视图构build应用程序,但不要使用导航控制器或Tab Bar控制器。 如果您手动交换视图进出UIWindow实例,您将不会可靠地收到这些消息。 这类似于这样的post: iPhone的viewWillAppear不开火

只要使用苹果公约的多个意见,你会没事的。 希望这可以节省一两个小时

它如何知道哪个UIViewController的视图作为窗口的子视图?

UIViewController类维护视图和视图控制器之间的静态映射。 这张地图在CocoaTouch里的几个关键位置被查询。 特别是,[UIView nextResponder]查询它并返回控制器,如果find。

我猜UIWindow做了相同的查找与它的根视图知道哪个控制器转发旋转事件。 下次我会在反汇编中查找一下。 (我花了一些时间对CocoaTouch进行反向工程,以了解这些工作是如何进行的。)

这是你永远不要担心的魔法。 只要将你的控制器的根视图添加到窗口 – 或者获得一个标签栏或导航控制器为你做 – 它会收到这些消息。

(但是如果你使用debugging器,你可能会得出同样的结论:有一些内部表将每个控制器的视图映射回控制器,并根据该链接调度消息。)


更新:这是2009年真正的私人魔术,当我第一次写这个答案,但后来的iOS的变化已经使公众背后的API。 现在可以通过UIWindow.rootViewController属性访问根视图控制器,而使用UIViewController.childViewControllers属性形成后代视图控制器树。

父视图控制器负责通知他们的孩子方向变化。 (我不知道如何通知根视图控制器,但你可以设置一个断点,并找出自己。)- -shouldAutomaticallyForwardRotationMethods方法决定是否UIViewController将为您做这个。 如果返回NO ,则在-willRotateToInterfaceOrientation:duration: ,- -willAnimateRotationToInterfaceOrientation:duration:-didRotateFromInterfaceOrientation:方法中负责这样做。

我有一个类似的问题。

我有一个横向的游戏(左右景观)。

为了pipe理一个多视图的应用程序,我使用了一个UI UIController,也就是一个带UIview的虚拟UIViewcontroller。 然后,我将其他所有UIview添加到它作为子视图。

当启动应用程序,模拟器快速旋转到肖像的方向,我得到我的每一个视图与它的框架属性看起来像(0,-80,320,480)。 这会导致视图被右侧的160 X 320矩形剪辑。

我注意到,每个子视图的 – shouldAutorotateToInterfaceOrientation:方法只被调用一次,并且当它被添加到根视图时会发生这种情况。 稍后,在旋转设备时,只有根视图才会调用该方法。

毫不奇怪,任何一个 – willAnimate *方法调用只发送到根视图,所以,在子视图中定义这些方法是毫无意义的。

每当方向改变为 – shouldAutorotateToInterfaceOrientation:方法所接受的方向时,就调用这些方法。 所以我想我可以从那里chnage我的子视图的框架属性。

为了做到这一点,我在我的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); ... } 

我不明白为什么框架属性不更新,但我知道这种解决方法的作品。

希望这可以帮助….