shouldAutorotateToInterfaceOrientation未在iOS 6中调用

Hes*_*gid 61 orientation ios ios6

我正在使用MGSplitViewController,我shouldAutorotateToInterfaceOrientation用来控制旋转时主视图控制器的大小.

它在iOS 5上运行良好,但在iOS 6(模拟器和iPad)shouldAutorotateToInterfaceOrientation上从未调用过.

这是一个我应该期望在iOS 6的最终版本中修复的错误或者我不知道已经改变的东西吗?

Boo*_*ker 128

请仔细阅读这篇文章,否则你可以在生命的1-2天内放松一下,疯狂地战斗,摇晃,转动你的测试设备就像动物园里的黑猩猩抓住了一个访客的手机!迟早......承诺:)

在iOS 6中

shouldAutorotateToInterfaceOrientation:
Run Code Online (Sandbox Code Playgroud)

被弃用并替换为

shouldAutorotate
Run Code Online (Sandbox Code Playgroud)

这意味着iOS 6永远不会打电话shouldAutorotateToInterfaceOrientation:

所以如果您在申请中使用了以下内容

iOS6 之前(iOS5,iOS4等)

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
if (interfaceOrientation == UIInterfaceOrientationPortrait) {
// your code for portrait mode

}

return YES;
}
Run Code Online (Sandbox Code Playgroud)

你应该使用

的iOS 6+

- (BOOL)shouldAutorotate {

UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation];

if (orientation == UIInterfaceOrientationPortrait) {
// your code for portrait mode

}

return YES;
}
Run Code Online (Sandbox Code Playgroud)

意识到

UIInterfaceOrientation是一个属性,UIApplication只包含4种可能性,它们对应于状态栏的方向:

UIInterfaceOrientationPortrait = UIDeviceOrientationPortrait,

UIInterfaceOrientationPortraitUpsideDown = UIDeviceOrientationPortraitUpsideDown,

UIInterfaceOrientationLandscapeLeft = UIDeviceOrientationLandscapeRight,

UIInterfaceOrientationLandscapeRight = UIDeviceOrientationLandscapeLeft
Run Code Online (Sandbox Code Playgroud)

不要混淆它

UIDeviceOrientation这是UIDevice该类的属性,包含7个可能的值:

UIDeviceOrientationUnknown - Can not be determined

UIDeviceOrientationPortrait - Home button facing down

UIDeviceOrientationPortraitUpsideDown - Home button facing up

UIDeviceOrientationLandscapeLeft - Home button facing right

UIDeviceOrientationLandscapeRight - Home button facing left

UIDeviceOrientationFaceUp - Device is flat, with screen facing up

UIDeviceOrientationFaceDown - Device is flat, with screen facing down
Run Code Online (Sandbox Code Playgroud)

即使你理论上可以使用UIDeviceOrientation orientation = [[UIDevice currentDevice] orientation];哪种返回UIDeviceOrientation- 设备的实际方向 - 但你必须知道UIDeviceOrientation并不总是相等UIInterfaceOrientation!例如,当您的设备位于普通表上时,您可以获得意外的价值.

你也可以使用UIInterfaceOrientation orientation = self.interfaceOrientation;哪个返回UIInterfaceOrientation,接口的当前方向,但它是属性UIViewController,所以你只能在UIViewController类中访问这个.

如果你想支持前iOS6的(IOS3/4/5)和iOS6的设备-这可能是显而易见的-只要同时使用shouldAutorotateToInterfaceOrientation:,并shouldAutorotate在你的代码.

从iOS 6开始,设备在应用程序启动期间会检查3个级别和3个步骤,如果您愿意,您必须控制它们.

1. Info.plist - Supported Interface Orientations
Run Code Online (Sandbox Code Playgroud)

您可以在摘要选项卡中以图形方式设置.允许的方向序列是重要的,您可以通过编辑手动更改info.plist,设备将在应用程序启动时选择第一个!这是至关重要的,因为当有可能[UIDevice currentDevice].orientation是未知的时候,问题始终是应用程序的启动,尤其是当我们在平面上测试我们的应用程序时.

XCode中的plist设置(信息)

注意事项 (iPad)或(iPhone)扩展有两种其他设置可能性,如果您使用其中任何一种,它将使用当前设备或模拟器的设置而忽略没有扩展名的常规设置.因此,如果您运行仅限iPhone的应用程序并且意外地在plist中的某个位置留下了"支持接口方向(iPad)"行,即使没有任何数据,它也会忽略您在常规设置中先前建立的规则(在我的iPhone示例中) )你可以拒绝你的应用程序的文字"我们发现你的应用程序不符合在iPad上运行的要求......"即使你的应用程序不打算在iPhone上使用给定的方向,但iPad将使用它可能会导致不可预测的错误,因为所有iPhone应用程序也必须在提交过程中在iPad上运行.

2. AppDelegate - application:supportedInterfaceOrientationsForWindow
Run Code Online (Sandbox Code Playgroud)

返回您想要允许的每个方向的位掩码列表,它会覆盖info.plist设置.每次设备旋转时至少调用一次.

3. Top-level view controller or RootViewController - supportedInterfaceOrientations
Run Code Online (Sandbox Code Playgroud)

它给出了与app和app delegate集合的交集,它必须具有非零结果以避免崩溃.每次设备旋转时至少调用一次,除非我们的控制器中安装了另一种方法:

shouldAutorotate
Run Code Online (Sandbox Code Playgroud)

这会干扰应用程序允许的方向,并提供BOOL默认值YES.

BE CAREFUL when you use `NavigationController`
Run Code Online (Sandbox Code Playgroud)

作为你最顶级的控制器AppDelegate,像这样:

DetailViewController *detailViewController = [[DetailViewController alloc] initWithNibName:@"DetailViewController" bundle:nil];
UINavigationController *navigationController=[[UINavigationController alloc] initWithRootViewController:detailViewController];
self.window.rootViewController =nil;
self.window.rootViewController = navigationController;
[self.window makeKeyAndVisible];
return YES;
Run Code Online (Sandbox Code Playgroud)

在这种情况下,您必须将以下代码AppDelegate作为类的附件放在您的NavigationController类中,因为这是最顶层的控制器,如果您还没有创建它的子类别,则您没有可以设置其方向的位置/代码设置,所以你需要强制它rootViewController在这种情况下检查你的真实detailViewController方向:

@implementation UINavigationController (OrientationSettings_IOS6)

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

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

- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation {
return [[self.viewControllers lastObject] preferredInterfaceOrientationForPresentation];
}

@end
Run Code Online (Sandbox Code Playgroud)

在此之后,您可以使用iOS 6中提供的任何方法在"最顶层" ViewController(在我的示例中为此detailViewController)中设置首选方向ViewControllers,如下所示:

1. (BOOL)shouldAutorotate

2. (NSUInteger)supportedInterfaceOrientations

3. (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
Run Code Online (Sandbox Code Playgroud)


Gen*_*ode 55

好吧,我让它在iOS6 iPad模拟器中工作.好极了.这是我做的:

我只是告诉你之前和之后,它应该是自我解释的:

之前

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {

if (interfaceOrientation==UIInterfaceOrientationPortrait) {
 // do some sh!t

}

return YES;
}
Run Code Online (Sandbox Code Playgroud)

- (BOOL)shouldAutorotate {

UIInterfaceOrientation orientation = [[UIDevice currentDevice] orientation];

if (orientation==UIInterfaceOrientationPortrait) {
 // do some sh!t

}

return YES;
}
Run Code Online (Sandbox Code Playgroud)

至于支持的方向,您可以在info.plist中指定: 支持的方向图

或使用代码:

-(NSUInteger)supportedInterfaceOrientations{
    return UIInterfaceOrientationMaskPortrait; // etc
}
Run Code Online (Sandbox Code Playgroud)

编辑:第二个想法,如果您打算支持较低版本(iOS4.3/5/5.1)以及6.0,那么只需包含具有相同代码内容的两种方法.适合我(无论如何都是sim)

  • 如果没有人想阅读下面的帖子,请注意设备在启动应用程序时可能不知道它的方向.因此,您可能还需要检查`if(orientation == UIDeviceOrientationUnknown)` (2认同)

小智 20

设置应用程序窗口路径控制器而不是只是添加它的视图作为子视图为我工作(如Rocotilos所做)

//    [self.window addSubview:self.topLevelNavigationController.view];
self.window.rootViewController = self.topLevelNavigationController;
Run Code Online (Sandbox Code Playgroud)

  • 这在iOS 6中不起作用.尝试以下操作:创建一个新的XCode项目并选择模板`Single View Application`.模板的"AppDelegate"已包含您建议的行.然后,在`ViewController`中覆盖`shouldAutorotateToInterfaceOrientation`,设置断点并对其进行调试.断点永远不会被击中(iOS 6). (12认同)

use*_*669 18

这是iOS 5及更早版代码的解决方案,不涉及复制逻辑.只需将此代码添加到视图控制器,它就会从现有的shouldAutorotateToInterfaceOrientation方法生成supportedInterfaceOrientations.

-(BOOL)shouldAutorotate{
    return YES;
}

-(NSInteger)supportedInterfaceOrientations{
NSInteger mask = 0;
if ([self shouldAutorotateToInterfaceOrientation: UIInterfaceOrientationLandscapeRight])
    mask |= UIInterfaceOrientationMaskLandscapeRight;
if ([self shouldAutorotateToInterfaceOrientation: UIInterfaceOrientationLandscapeLeft])
    mask |= UIInterfaceOrientationMaskLandscapeLeft;
if ([self shouldAutorotateToInterfaceOrientation: UIInterfaceOrientationPortrait])
    mask |= UIInterfaceOrientationMaskPortrait;
if ([self shouldAutorotateToInterfaceOrientation: UIInterfaceOrientationPortraitUpsideDown])
    mask |= UIInterfaceOrientationMaskPortraitUpsideDown;
return mask;
}
Run Code Online (Sandbox Code Playgroud)


小智 15

我的快速解决方法是在我的根视图控制器上添加此代码

- (BOOL)shouldAutorotate {
    return [self shouldAutorotateToInterfaceOrientation:self.interfaceOrientation];
}
Run Code Online (Sandbox Code Playgroud)

这样我仍然使用与iOS 6之前的版本相同的逻辑.当然,我最初在我的应用程序中设置了我的rootViewController委托didFinishLaunchingWithOptions而不是仅添加到windows子视图.

  • 嗯,shouldAutorotate不应该被弃用,但是应该是AutorotateToInterfaceOrientation.但是,这只意味着操作系统不再调用它.如果你已经实现了它,它可以自由地调用它.它不会弃用.当然,这与ios 6的变化有关. (4认同)
  • 但是这种方法又折旧了.对吗? (2认同)

Chr*_*ing 11

虽然许多响应都指出了解决方案 - 要实现iOS 6构建的shouldAutorotate和supportedInterfaceOrientations,但您还应该知道,如果您的视图控制器托管在导航控制器中,那么它们都不重要,因为运行时将在UINavigationController实例上调用它们,否则忽略您的代码.

显然,'解决方案'是子类UINavigationController并在此子类上实现这些新方法,如下所述: iOS 6 UITabBarController支持使用当前UINavigation控制器的方向

然后,您可以更改所有代码,使用UINavigationController来代替使用这个新的子类.

这必须是我见过的iOS版本中最无意义和烦人的突破性变化之一.


小智 10

IOS 5

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation{
if (UIInterfaceOrientationLandscapeLeft) {
        return (interfaceOrientation == UIInterfaceOrientationLandscapeLeft);
    }
    if (UIInterfaceOrientationLandscapeRight) {
        return (interfaceOrientation == UIInterfaceOrientationLandscapeRight);
    }
    return (interfaceOrientation == UIInterfaceOrientationLandscapeLeft);
}
Run Code Online (Sandbox Code Playgroud)

IOS 6

-(BOOL)shouldAutorotate{
    return YES;
}

-(NSInteger)supportedInterfaceOrientations:(UIWindow *)window{

    //    UIInterfaceOrientationMaskLandscape;
    //    24
    //
    //    UIInterfaceOrientationMaskLandscapeLeft;
    //    16
    //
    //    UIInterfaceOrientationMaskLandscapeRight;
    //    8
    //
    //    UIInterfaceOrientationMaskPortrait;
    //    2


    //    return UIInterfaceOrientationMaskLandscape;
    return 24;
}
Run Code Online (Sandbox Code Playgroud)

  • 使用|| 运算符而不是幻数.这将使阅读更容易! (11认同)
  • 我相信supportedInterfaceOrientations:(UIWindow*)窗口应该是supportedInterfaceOrientations. (2认同)

小智 3

这对我来说适用于 iOS6 和 Xcode 4.5 GM:

在 AppDelegate.m 上

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    .....

    //   self.window.rootViewController = self.navigationController;

    [window setRootViewController:navigationController];

    .....

    return YES;
}
Run Code Online (Sandbox Code Playgroud)

在视图控制器上:

- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation duration:(NSTimeInterval)duration

{
    if (UIInterfaceOrientationIsLandscape(interfaceOrientation))

    {
      // landscape
    }
    else
    {
      //portrait
    }
}
Run Code Online (Sandbox Code Playgroud)