【问题标题】:supportedInterfaceOrientations not working支持的接口方向不起作用
【发布时间】:2014-02-14 17:28:12
【问题描述】:

我想要一些我的 ViewControllers 横向和一些纵向,所以这就是我所做的:

我启用了横向模式:

接下来我将这些代码行添加到我想成为 Portrait 的视图控制器中:

-(NSUInteger)supportedInterfaceOrientations
{
    return UIInterfaceOrientationPortrait;
}
-(BOOL)shouldAutorotate
{
    return NO;
}
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation {
    return UIInterfaceOrientationPortrait;
}

但是当我旋转它们时,它们仍然会进入横向模式。我该如何解决这个问题?

【问题讨论】:

  • 你的 viewController 中可能有这些方法,它们被推送到 UINavigationController 中,对吧?

标签: ios orientation


【解决方案1】:

为简单起见,对于 iPad,如果 info.plist 中的 Supported interface orientations (iPad) 属性包含所有四个方向,则 UIRequiresFullScreen 属性值为 NO ,iOS 会将您的应用视为支持拆分视图。如果一个应用程序支持拆分视图功能,你不能禁止它旋转,至少通过上述方式。


让我们深入了解细节。

首先,我们需要知道哪些因素会影响屏幕方向:

1.项目设置(info.plist)

有两个地方我们可以做这个设置:

  • 项目->目标->常规->设备方向

  • 项目的info.plist

这两种方法相同,一种会自动同步另一种设置。 在 info.plist 文件中,Supported interface orientations (iPad) 属性用于 iPad 设置(为 Device 部分选择 iPad),并且 支持的界面方向 属性适用于 iPhone 和 Universal(选择 iPhoneUniversal 用于 Device 部分,这两个设置将始终为一样。)。

2。以编程方式设置支持的屏幕方向

有两种方法可以在编码时配置支持的方向:

  • supportedInterfaceOrientationsForWindow: 中的 UIApplicationDelegate 方法
  • supportedInterfaceOrientationsUIViewController 中的方法

iOS 系统会检查这两种方法中定义的共同方向,并将共同方向作为视图控制器支持的方向。

3.在UIViewController中设置shouldAutorotate属性

这是一个只读属性,用于控制视图控制器是否可旋转。您可以在视图控制器中覆盖该属性,甚至将该属性更改为读写属性,以便您可以在应用程序运行时修改该属性。例如:

override public var shouldAutorotate: Bool {
    get {
        return self.shouldAutorotateVariable
    }
    set {
        self.shouldAutorotateVariable = newValue
    }
}

shouldAutorotateVariable 是视图控制器中的私有属性。

iPhone

如果视图控制器的shouldAutorotate 属性设置为false,iOS 将省略以下设置:

  • supportedInterfaceOrientationsForWindow:UIApplicationDelegate 中的方法
  • supportedInterfaceOrientations 中的 UIViewController 方法

iOS 将仅使用项目设置 (info.plist)。

如果shouldAutorotate 属性未被覆盖或设置为true,则iOS 将使用以下两种方法中定义的常用方向:

  • supportedInterfaceOrientationsForWindow:UIApplicationDelegate 中的方法
  • supportedInterfaceOrientationsUIViewController 中的方法

如果没有提供以上两种方法,iOS 将使用项目设置(info.plist)。

iPad

从 iOS9 开始,iPad 支持拆分视图功能。分屏设置参考Slide Over and Split View Quick Start

为简单起见,如果 info.plist 中的 Supported interface orientations (iPad) 属性包括所有四个方向,则 UIRequiresFullScreen 属性值为 NO,iOS 会将您的应用视为支持拆分视图。如果应用支持拆分视图,以下两项设置将被省略:

  • supportedInterfaceOrientationsForWindow:UIApplicationDelegate 中的方法
  • supportedInterfaceOrientations 中的 UIViewController 方法

UIViewController 中的 shouldAutorotate 属性也将被省略。

也就是说,如果一个应用程序支持拆分视图功能,你不能禁用它的旋转,至少通过上述方式。

如果 info.plist 值中的支持的界面方向 (iPad) 属性不包括所有四个方向,或者 UIRequiresFullScreen 属性设置为 YES em>,该应用将不支持分屏,屏幕方向控制逻辑与上面的iPhone相同。

注意:对于项目设置(info.plist),最好直接在info.plist里面设置以下三个属性:

  • 支持的界面方向 (iPad)
  • 支持的界面方向
  • UIRequiresFullScreen

如果你尝试通过Project->Target->General->Device Orientation设置会很混乱:甚至Device被设置为UniverseiPad中的设置仍然会生效。

【讨论】:

    【解决方案2】:

    这是我的做法。
    创建一个 UINavigationController 父类。
    在你内部 UINavigationController (parent) 覆盖这些方法,如:

    - (NSUInteger)supportedInterfaceOrientations
    {
        if([self.topViewController respondsToSelector:@selector(supportedInterfaceOrientationsForThisContorller)])
        {
            return(NSInteger)[self.topViewController performSelector:@selector(supportedInterfaceOrientationsForThisContorller) withObject:nil];
        }
        return UIInterfaceOrientationPortrait;
    }
    
    - (BOOL)shouldAutorotate
    {
        if([self.visibleViewController respondsToSelector:@selector(shouldAutorotateNow)])
        {
            BOOL autoRotate = (BOOL)[self.visibleViewController
                                performSelector:@selector(shouldAutorotateNow)
                                withObject:nil];
            return autoRotate;
    
        }
        return NO;
    }
    

    现在您的 NavigationController 应该是 UINavigationContorller 父级的子类

    斯威夫特 3:

    在您的 UINavigationController 子类中执行此操作

    override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
            get {
                return self.topViewController?.supportedInterfaceOrientations ?? .all
            }
        }
    
    override var shouldAutorotate: Bool {
            return self.topViewController?.shouldAutorotate ?? false
        }
    

    更新 如果您不想子类化,取自 Matt 的 answer

    首先:让你的viewController成为viewDidLoad中的navigationController的代表

    self.navigationController?.delegate = self
    

    然后声明UIViewController扩展响应委托方法如下图:

    extension UIViewController: UINavigationControllerDelegate {
        public func navigationControllerSupportedInterfaceOrientations(_ navigationController: UINavigationController) -> UIInterfaceOrientationMask {
            return navigationController.topViewController?.supportedInterfaceOrientations
        }
    }
    

    【讨论】:

    • 把它放在我的视图控制器中?
    • 或者创建一个自定义导航控制器?
    • 不,这是在 UINavigationController 类里面,创建这个类的实例,然后推送你的 viewControllers
    • @AbdullahShafique,没错
    • 请注意,我在 UIViewControllers 中添加了 - (BOOL)shouldAutoRotateNow,以防其他类处理相同的方法,因此只有具有此方法名称的类才能响应
    【解决方案3】:

    Apple 为UINavigationController 设计的方法是通过UINavigationControllerDelegate

    通常我只是更新此委托以执行以下操作并将其委托给导航控制器堆栈中的顶部显示控制器:

    #pragma mark - UINavigationControllerDelegate
    
    - (NSUInteger)navigationControllerSupportedInterfaceOrientations:(UINavigationController *)navigationController
    {
        return [navigationController.topViewController supportedInterfaceOrientations];
    }
    

    在我看来,UINavigationController 应该只是默认为上述行为,但这是 Apple 提供的 api :)

    至于 info plist 文件,我取消选中所有选项并在代码中处理它,因为它过去曾给我带来问题,我已经厌倦了处理它。

    【讨论】:

    • 我的代码中没有调用这个方法。我负责呈现视图控制器的父类是实现 UINavigationControllerDelegate 的父类,但是……不,没有调用。
    【解决方案4】:

    在 UINavigationController 下,我正在实现 UINavigationControllerDelegate 和以下方法:

    #pragma mark - From UINavigationControllerDelegate
    
    -(UIInterfaceOrientationMask) navigationControllerSupportedInterfaceOrientations:(UINavigationController*)navigationController {
        return UIInterfaceOrientationMaskPortrait; // TODO: change to whatever you need to allow
    }
    

    【讨论】:

    • 自动旋转是否也有一个?我这样做了,它只被正确调用为纵向,但我的状态栏仍然横向旋转
    【解决方案5】:

    只为您提供所有信息, 创建一个新的项目基于单一视图的应用程序, 在 viewController 中实现应该自动旋转委托和supportedInterface 方向 在其中添加断点。

    运行(通用模式)

    1. 在 iphone 模拟器上:执行在断点处停止
    2. 在 ipad 模拟器上:执行不会停止(永远不会调用委托方法!!!!)
    3. 在 ipad 设备上:好的

    所以不要像我刚才那样在它上面浪费太多时间,XCode 7.3 是 BUGGED

    【讨论】:

    • 你解决了吗?我现在有同样的问题 - 使用 iPhone bot 而不是 iPad
    • @jeyben 据我所知,没有什么可以解决的,这只是一个模拟器错误。在真机上试一试,一切正常
    【解决方案6】:

    你可以在下面的帖子中看到答案:

    iOS 6 rotations: supportedInterfaceOrientations doesn´t work?

    如果是你的问题,请告诉我。

    【讨论】:

      【解决方案7】:

      如果上述解决方案不起作用,那么如果您使用的是UITabBarController,那么您需要继承UITabBarController 并需要覆盖以下方法

      override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
          return .portrait
      } 
      

      我建议你使用.all 代替iPad 这里是扩展的

       override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
           return UIDevice.current.userInterfaceIdiom == .phone ? [.portrait, .portraitUpsideDown] : .all
      
         }
      

      希望对遇到同样问题的人有所帮助

      【讨论】:

        猜你喜欢
        • 2015-12-23
        • 1970-01-01
        • 2016-07-28
        • 1970-01-01
        • 1970-01-01
        • 2013-07-25
        • 2015-02-26
        • 1970-01-01
        相关资源
        最近更新 更多