ios UIViewController 旋转方法

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/548142/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-30 15:38:32  来源:igfitidea点击:

UIViewController rotate methods

iphoneioscocoa-touchuiviewcontroller

提问by Corey Floyd

What object is responsible for dipatching the UIViewControllerrotation method calls, i.e:

哪个对象负责分配UIViewController旋转方法调用,即:

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

I imagine it is UIApplication(but maybe the AppDelegate or UIWindow).

我想是UIApplication(但可能是 AppDelegate 或 UIWindow)。

The next question, is how does the object know which UIViewControllerto talk to?

下一个问题是,对象如何知道UIViewController要与哪个对话?

How does it know which UIViewControllerhas its view as the subview of the window?

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

Is there a message you can send or a property you can set (of some object) that sets the "Active" UIViewControllerfor the app?

是否有您可以发送的消息或您可以设置的(某些对象的)属性来设置UIViewController应用程序的“活动” ?

采纳答案by Corey Floyd

It seems that UIApplicationis dispatching a message to the active view controller.

似乎UIApplication正在向活动视图控制器发送消息。

But how does your View Controller instance get these messages?

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

The message is forwarded to the first view controller whose view has been added to the UIWindowinstance.

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

This boils down to 3 basic scenarios:

这归结为 3 个基本场景:

  1. The ViewController whose view is added directly to the UIWindowinstance (single view app)

  2. The navigation Controller in a Navigation based app, then the navigation controller forwards the message to the active views view controller.

  3. The tab bar Controller in a tab bar based app, then the tab bar controller forwards the message to the active views view controller (or the active navigation controller).

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

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

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

The problem you will have, is if you build an app with multiple views, but DO NOT use a Navigation controller or Tab Bar controller. If you swap views in and out of the UIWindowinstance manually, you will not receive these messages reliably. This is similar to posts like this one: iPhone viewWillAppear not firing

您将遇到的问题是,如果您构建具有多个视图的应用程序,但不要使用导航控制器或标签栏控制器。如果您UIWindow手动交换视图进出实例,您将无法可靠地接收这些消息。这类似于这样的帖子: iPhone viewWillAppear not fire

Just use Apple's conventions for multiple views and you be fine. Hope this saves some one an hour or two

只需将 Apple 的约定用于多个视图,就可以了。希望这可以节省一两个小时的时间

回答by Andrey Tarantsov

How does it know which UIViewController has its view as the subview of the window?

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

UIViewController class maintains a static map between views and their view controllers. This map is queried in a few key places inside CocoaTouch. In particular, [UIView nextResponder] queries it and returns the controller if found.

UIViewController 类维护视图与其视图控制器之间的静态映射。在 CocoaTouch 内部的几个关键地方查询了这张地图。特别是,[UIView nextResponder] 查询它并在找到时返回控制器。

I guess UIWindow does the same lookup with its root view to know which controller to forward rotation events to. Will check this next time I'll be looking something up in the disassembly. (I've spent some time reverse-engineering CocoaTouch to understand how things work there.)

我猜 UIWindow 对其根视图执行相同的查找,以了解将旋转事件转发到哪个控制器。下次我会在反汇编中查找一些东西时会检查这个。(我花了一些时间对 CocoaTouch 进​​行逆向工程,以了解那里的工作原理。)

回答by Brent Royal-Gordon

This is all Magic You Don't Ever Worry About. Just add your controller's root view to the window--or get a tab bar or navigation controller to do it for you--and it will receive these messages.

这就是您永远不必担心的所有魔法。只需将您的控制器的根视图添加到窗口中——或者获取一个标签栏或导航控制器来为您完成——它就会收到这些消息。

(But if you poke around with the debugger, you might come to the same conclusion I have: there's some sort of internal table mapping each controller's view back to the controller, and the messages are dispatched based on that link.)

(但是,如果您仔细研究调试器,您可能会得出与我相同的结论:有某种内部表将每个控制器的视图映射回控制器,并且基于该链接发送消息。)



Update:This was truly private magic in 2009 when I first wrote this answer, but subsequent changes to iOS have made the APIs behind it public. The root view controller is now accessible through the UIWindow.rootViewControllerproperty, and the tree of descendant view controllers is formed using the UIViewController.childViewControllersproperty.

更新:在 2009 年我第一次写这个答案时,这真的是私人魔术,但随后对 iOS 的更改已将其背后的 API 公开。现在可以通过该UIWindow.rootViewController属性访问根视图控制器,并且使用该UIViewController.childViewControllers属性形成后代视图控制器树。

Parent view controllers are responsible for notifying their children of orientation changes. (I'm not sure how the root view controller is notified, but you could set a breakpoint and find out yourself.) The -shouldAutomaticallyForwardRotationMethodsmethod decides whether UIViewController will do this for you. If it returns NO, you become responsible for doing so in your -willRotateToInterfaceOrientation:duration:, -willAnimateRotationToInterfaceOrientation:duration:, and -didRotateFromInterfaceOrientation:methods.

父视图控制器负责通知他们的孩子方向变化。(我不确定如何通知根视图控制器,但您可以设置断点并自行查找。)该-shouldAutomaticallyForwardRotationMethods方法决定 UIViewController 是否会为您执行此操作。如果返回NO,你成为负责你这样做-willRotateToInterfaceOrientation:duration:-willAnimateRotationToInterfaceOrientation:duration:-didRotateFromInterfaceOrientation:方法。

回答by OliveiraX

I have a similar problem.

我有一个类似的问题。

I have a game working in landscape orientation (both left and right landscape).

我有一个横向运行的游戏(左右横向)。

In order to manage a multi-view application I use a root UIviewController, i.e. a dummy UIViewcontroller with a UIview that does nothing. I then add every other UIview to it as a subview.

为了管理一个多视图应用程序,我使用了一个根 UIviewController,即一个虚拟的 UIViewController,带有一个什么都不做的 UIview。然后我将所有其他 UIview 添加到它作为子视图。

When starting the app, the emulator quickly rotates to a portrait orientation, and i get every one of my views with it's frame property looking like (0,-80,320,480). This results in the view being clipped by a 160 X 320 rectangle on the right side.

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

I've noticed that the – shouldAutorotateToInterfaceOrientation: method of each subview is only called once, and that happens when it is added to the root view. Later on, when rotating the device, only the root view gets it's method called.

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

Unsurprisingly, any one of the – willAnimate* methods calls are only sent to the root view, so, defining any of these methods in subviews is pointless.

不出所料,任何一个 – willAnimate* 方法调用都只会发送到根视图,因此,在子视图中定义这些方法中的任何一个都是毫无意义的。

These methods are called everytime the orientation is changed to an orientation accepted by the – shouldAutorotateToInterfaceOrientation: method. so I figured i could chnage my subviews' frame property from there.

每次将方向更改为 – shouldAutorotateToInterfaceOrientation: 方法接受的方向时,都会调用这些方法。所以我想我可以从那里更改我的子视图的框架属性。

To accomplish this, I defined the following method in my rootViewController class:

为此,我在 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);
        ...
}

I don't understand why the frame property is not updated, but I know this workaround works.

我不明白为什么不更新 frame 属性,但我知道这种解决方法有效。

Hope this helps....

希望这可以帮助....