iOS 6 中的自动旋转有奇怪的行为

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/12526054/
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 20:17:32  来源:igfitidea点击:

Autorotate in iOS 6 has strange behaviour

iphoneobjective-ciosmpmovieplayercontrollerios6

提问by Timur Mustafaev

I have UITabBarControllerapp which plays video and shows other information in other UITabBartabs. In iOS 6 UIViewrotation methods have been deprecated, and now I need to use shouldAutoRotateand supportedInterfaceOrientationsmethods. For video playing I use MPMoviePlayerViewController.

我有UITabBarController播放视频并在其他UITabBar选项卡中显示其他信息的应用程序。在 iOS 6 中UIView旋转方法已被弃用,现在我需要使用shouldAutoRotatesupportedInterfaceOrientations方法。对于视频播放,我使用MPMoviePlayerViewController.

How to rotate only this player view? I can only rotate whole app, but don't want to do this. I present MPMoviePlayerViewControllerbut it doesn't rotate as in iOS 5 and earlier.

如何仅旋转此播放器视图?我只能旋转整个应用程序,但不想这样做。我展示了MPMoviePlayerViewController它,但它不像在 iOS 5 及更早版本中那样旋转。

In plistsetting I've set only 1 Portrait interface orientation. If I set other - whole app will be rotated.

plist设置中,我只设置了 1 个纵向界面方向。如果我设置其他 - 整个应用程序将被旋转。

回答by rocky

From Apple's iOS 6 SDK Release Notes:

来自 Apple 的 iOS 6 SDK 发行说明:

Autorotation is changing in iOS 6. In iOS 6, the shouldAutorotateToInterfaceOrientation: method of UIViewController is deprecated. In its place, you should use the supportedInterfaceOrientationsForWindow: and shouldAutorotate methods.

More responsibility is moving to the app and the app delegate. Now, iOS containers (such as UINavigationController) do not consult their children to determine whether they should autorotate. By default, an app and a view controller's supported interface orientations are set to UIInterfaceOrientationMaskAll for the iPad idiom and UIInterfaceOrientationMaskAllButUpsideDown for the iPhone idiom.

A view controller's supported interface orientations can change over time—even an app's supported interface orientations can change over time. The system asks the top-most full-screen view controller (typically the root view controller) for its supported interface orientations whenever the device rotates or whenever a view controller is presented with the full-screen modal presentation style.Moreover, the supported orientations are retrieved only if this view controller returns YES from its shouldAutorotate method. The system intersects the view controller's supported orientations with the app's supported orientations (as determined by the Info.plist file or the app delegate's application:supportedInterfaceOrientationsForWindow: method) to determine whether to rotate.

The system determines whether an orientation is supported by intersecting the value returned by the app's supportedInterfaceOrientationsForWindow: method with the value returned by the supportedInterfaceOrientations method of the top-most full-screen controller. The setStatusBarOrientation:animated: method is not deprecated outright. It now works only if the supportedInterfaceOrientations method of the top-most full-screen view controller returns 0. This makes the caller responsible for ensuring that the status bar orientation is consistent.

For compatibility, view controllers that still implement the shouldAutorotateToInterfaceOrientation: method do not get the new autorotation behaviors. (In other words, they do not fall back to using the app, app delegate, or Info.plist file to determine the supported orientations.) Instead, the shouldAutorotateToInterfaceOrientation: method is used to synthesize the information that would be returned by the supportedInterfaceOrientations method.

Autorotation 在 iOS 6 中发生了变化。在 iOS 6 中,不推荐使用 UIViewController 的 shouldAutorotateToInterfaceOrientation: 方法。在其位,你应该使用supportedInterfaceOrientationsForWindow:和shouldAutorotate方法。

更多的责任正在转移到应用程序和应用程序委托上。现在,iOS的容器(如UINavigationController的)不咨询自己的孩子,以确定他们是否应该自动旋转。默认情况下,应用程序和视图控制器支持的界面方向设置为 UIInterfaceOrientationMaskAll(对于 iPad 习惯用法)和 UIInterfaceOrientationMaskAllButUpsideDown(对于 iPhone 习惯用法)。

视图控制器支持的界面方向会随着时间的推移而改变——甚至应用程序支持的界面方向也会随着时间的推移而改变。每当设备旋转或视图控制器以全屏模式呈现样式呈现时,系统都会向最顶层的全屏视图控制器(通常是根视图控制器)询问其支持的界面方向。此外,仅当此视图控制器从它的 shouldAutorotate 方法返回 YES 时,才会检索支持的方向。系统将视图控制器支持的方向与应用程序支持的方向(由 Info.plist 文件或应用程序委托的 application:supportedInterfaceOrientationsForWindow: 方法确定)相交以确定是否旋转。

系统通过将应用程序的 supportedInterfaceOrientationsForWindow: 方法返回的值与最顶层全屏控制器的 supportedInterfaceOrientations 方法返回的值相交来确定是否支持某个方向。setStatusBarOrientation:animated: 方法并未完全弃用。它现在只有在最顶层全屏视图控制器的 supportedInterfaceOrientations 方法返回 0 时才起作用。这使得调用者负责确保状态栏方向一致。

为了兼容性,仍然实现 shouldAutorotateToInterfaceOrientation: 方法的视图控制器不会获得新的自动旋转行为。(换句话说,他们不会回退到使用应用程序、应用程序委托或 Info.plist 文件来确定支持的方向。)相反, shouldAutorotateToInterfaceOrientation: 方法用于合成由 supportedInterfaceOrientations 方法返回的信息.

If you want your whole app to rotate then you should set your Info.plist to support all orientations. Now if you want a specific view to be portrait only you will have to do some sort of subclass and override the autorotation methods to return portrait only. I have an example here:

如果您希望整个应用程序旋转,那么您应该将 Info.plist 设置为支持所有方向。现在,如果您希望特定视图仅显示肖像,则必须执行某种子类并覆盖自动旋转方法以仅返回肖像。我这里有一个例子:

https://stackoverflow.com/a/12522119/1575017

https://stackoverflow.com/a/12522119/1575017

回答by Agat

Ough! A half of a day spent, and the problem solved! He he.

哎哟!一天半时间了,问题解决了!呵呵。

As the documentation above says, this is really it! The core points are:

正如上面的文档所说,确实如此!核心要点是:

More responsibility is moving to the app and the app delegate. Now, iOS containers (such as UINavigationController) do not consult their children to determine whether they should autorotate. By default, an app and a view controller's supported interface orientations are set to UIInterfaceOrientationMaskAll for the iPad idiom and UIInterfaceOrientationMaskAllButUpsideDown for the iPhone idiom.

更多的责任正在转移到 app 和 app delegate 上。现在,iOS 容器(例如 UINavigationController)不会咨询他们的孩子来确定他们是否应该自动旋转。默认情况下,应用程序和视图控制器支持的界面方向设置为 UIInterfaceOrientationMaskAll(对于 iPad 习惯用法)和 UIInterfaceOrientationMaskAllButUpsideDown(对于 iPhone 习惯用法)。

So, any time something with root controller changes, the system asks app delegate "So, what are we? Rotating or not?"

因此,每当根控制器发生变化时,系统都会询问应用程序委托“那么,我们是什么?是否旋转?”

If "rotating":

如果“旋转”:

the supported orientations are retrieved only if this view controller returns YES from its shouldAutorotate method

仅当此视图控制器从它的 shouldAutorotate 方法返回 YES 时才检索支持的方向

then system asks our app delegate for

然后系统要求我们的应用程序委托

- (NSUInteger) application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window {    

    return ...;
}

That's really pretty simple.

这真的很简单。

How to determine when should we allow Portrait or Landscape etc - is up to you. Testing for root controller didn't work for me because of some points, but this works:

如何确定我们何时应该允许纵向或横向等 - 取决于您。由于某些原因,对根控制器的测试对我不起作用,但这有效:

- (NSUInteger) application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window {    

    return self.fullScreenVideoIsPlaying ?
        UIInterfaceOrientationMaskAllButUpsideDown :
        UIInterfaceOrientationMaskPortrait;
}

The property "fullScreenVideoIsPlaying" is set up by me manually whenever I need that.

每当我需要时,我都会手动设置“fullScreenVideoIsPlaying”属性。

The only other important thing to be careful is the enum. As it says in docs ... (read carefully above iPad/iPhone thing). So, you can play with those as you need.

唯一需要注意的其他重要事项是枚举。正如它在文档中所说的......(仔细阅读 iPad/iPhone 上面的内容)。因此,您可以根据需要使用它们。

Another tiny thing was some buggy behaviour after closing the player controller. There was one time when it did not change the orientation, but that happened once and in some strange way, and only in simulator (iOS 6 only, of course). So I even could not react, as it happened unexpectedly and after clicking fast on some other elements of my app, it rotated to normal orientation. So, not sure - might be some delay in simulator work or something (or, really a bug :) ).

另一件小事是关闭播放器控制器后的一些错误行为。有一次它没有改变方向,但这种情况以某种奇怪的方式发生过一次,而且只发生在模拟器中(当然,仅限于 iOS 6)。所以我什至无法做出反应,因为它出乎意料,在我的应用程序的其他一些元素上快速点击后,它旋转到正常方向。所以,不确定 - 可能是模拟器工作延迟或其他(或者,真的是一个错误:))。

Good luck!

祝你好运!

回答by Vipin Johney

I had the same problem with my app.

我的应用程序遇到了同样的问题。

How the rotation in iOS 6 work is that.

iOS 6 中的旋转是如何工作的。

=> when ever you are using UINavigationCOntroller the method in AppDelegate

=> 当你使用 UINavigationCONtroller AppDelegate 中的方法时

- (NSUInteger) application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window    
{
   return 
}

decides whether to rotate or not.

决定是否旋转。

=> when the view is presented in the Modal presentation style the method

=> 当视图以 Modal 呈现风格呈现时,该方法

- (BOOL)shouldAutorotate

which is inside the viewController for that view triggers the method in the appDelegate. And as 1st case appDelegate decides to rotate or not.

该视图的 viewController 内部会触发 appDelegate 中的方法。作为第一种情况,appDelegate 决定是否旋转。

My Solution::

我的解决方案::

What I did for Modal presentation was that. Created a flag in app delegate.

我为 Modal 演示所做的就是这样。在应用程序委托中创建了一个标志。

when ever the flag is YES it rotates to Landscape and else its only Portrait.

当标志为 YES 时,它会旋转为横向,否则为唯一的纵向。

- (NSUInteger)application:(UIApplication*)application
supportedInterfaceOrientationsForWindow:(UIWindow*)window
{
    if(self.shouldRotate ) //shouldRotate is my flag
    {
        self.shouldRotate = NO;
        return (UIInterfaceOrientationMaskAll);
    }
    return (UIInterfaceOrientationMaskPortrait);
}

And to toggle between rotations

并在旋转之间切换

- (BOOL)shouldAutorotate
{
    YourAppDelegate *mainDelegate = (YourAppDelegate*)[[UIApplication sharedApplication]delegate];
    mainDelegate.shouldRotate = YES;

    return YES;
}

Note: This works is only for view that are Modely Presented. Using Flag, not a good coding practice.

注意:这仅适用于模型呈现的视图。使用 Flag,不是一个好的编码习惯。

回答by Serge Kutny

You can also subclass UITabBarController to make it ask its children about the shouldAutorotate and supportedInterfaceOrientation like this:

你也可以子类化 UITabBarController 让它像这样询问它的子节点 shouldAutorotate 和 supportedInterfaceOrientation :

@implementation MyTabBarController

-(BOOL)shouldAutorotate
{
    return [self.selectedViewController shouldAutorotate];
}

-(NSUInteger)supportedInterfaceOrientations
{
    return [self.selectedViewController supportedInterfaceOrientations];
}

@end

Then you just use your custom container in place of the standard one and it works! just tested.

然后您只需使用您的自定义容器代替标准容器即可!刚刚测试。

回答by Anthony

Unfortunately you'll need to turn on all orientations in your plist and use supportedInterfaceOrientations on all the view controllers you don't want to rotate. (In your case everything but the video player.)

不幸的是,您需要打开 plist 中的所有方向,并在您不想旋转的所有视图控制器上使用 supportedInterfaceOrientations。(在您的情况下,除了视频播放器之外的所有内容。)

回答by Vinay

Try this,

尝试这个,

If TabBarController is RootViewController for window, Then Create Custom Class which inherits TabBarController say CustomTabBarController.h

如果 TabBarController 是窗口的 RootViewController,则创建继承 TabBarController 的自定义类说 CustomTabBarController.h

Add Below method in CustomTabBarController.h

在 CustomTabBarController.h 中添加下面的方法

-(NSUInteger)supportedInterfaceOrientations // Must return Orientation Mask

Finally Call Below in AppDelegate.m

最后在 AppDelegate.m 中调用下面

- (NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window  {
   if( [self.window.rootViewController supportedInterfaceOrientations]!=0) 
     {
        return [self.window.rootViewController supportedInterfaceOrientations];
    }
    return UIInterfaceOrientationMaskAll;
}

回答by Tim

I found the easiest way to set this up is to use the "supported interface orientations" buttons which you can see if you look at Targets....Summary Tab (under iPhone/iPad Deployment info).

我发现设置它的最简单方法是使用“支持的界面方向”按钮,如果您查看 Targets....Summary Tab(在 iPhone/iPad 部署信息下),您可以看到这些按钮。

Its basically a GUI to set the plist file

它基本上是一个用于设置 plist 文件的 GUI