supportedInterfaceOrientations无法正常工作

Abd*_*que 12 orientation ios

我想要一些我的ViewControllers景观和一些肖像,所以这就是我做的:

我启用了横向模式:

在此输入图像描述

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

-(NSUInteger)supportedInterfaceOrientations
{
    return UIInterfaceOrientationPortrait;
}
-(BOOL)shouldAutorotate
{
    return NO;
}
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation {
    return UIInterfaceOrientationPortrait;
}
Run Code Online (Sandbox Code Playgroud)

然而,当我旋转它们时,它们仍然会进入横向模式.我怎么能解决这个问题?

小智 22

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

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

#pragma mark - UINavigationControllerDelegate

- (NSUInteger)navigationControllerSupportedInterfaceOrientations:(UINavigationController *)navigationController
{
    return [navigationController.topViewController supportedInterfaceOrientations];
}
Run Code Online (Sandbox Code Playgroud)

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

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

  • 我的代码中未调用此方法。我的父类负责呈现视图控制器,它是实现UINavigationControllerDelegate的类,但是...不,不被调用。 (3认同)

Hon*_*ang 17

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


让我们深入了解细节。

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

1.项目设置?info.plist?

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

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

    项目设置中的屏幕方向设置

  • 项目的 info.plist

    info.plist 中的屏幕方向设置

这两种方法是一样的,一种会自动同步另一种设置。在Info.plist文件,支持的接口方向(新iPad),属性是为iPad设置(可选择的iPad设备部分),并支持的接口方向属性是iPhone和万能(选择iPhone通用设备部分,这两个设置将始终是相同的。)。

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

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

  • supportedInterfaceOrientationsForWindow: 方法在 UIApplicationDelegate
  • supportedInterfaceOrientations 方法在 UIViewController

iOS 系统会检查两个方法中定义的通用方向,并使用通用方向作为视图控制器支持的方向。

3.设置shouldAutorotate属性UIViewController

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

override public var shouldAutorotate: Bool {
    get {
        return self.shouldAutorotateVariable
    }
    set {
        self.shouldAutorotateVariable = newValue
    }
}
Run Code Online (Sandbox Code Playgroud)

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

苹果手机

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

  • supportedInterfaceOrientationsForWindow: 方法在 UIApplicationDelegate
  • supportedInterfaceOrientations 方法在 UIViewController

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

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

  • supportedInterfaceOrientationsForWindow: 方法在 UIApplicationDelegate
  • supportedInterfaceOrientations 方法在 UIViewController

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

iPad

从 iOS9 开始,iPad 支持分屏功能。拆分视图的设置请参考Slide Over 和拆分视图快速入门

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

  • supportedInterfaceOrientationsForWindow: 方法在 UIApplicationDelegate
  • supportedInterfaceOrientations 方法在 UIViewController

shouldAutorotate财产UIViewController也将被省略。

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

如果info.plist 值中Supported interface orientations (iPad)属性不包含所有四个方向,或者UIRequiresFullScreen属性设置为YES,则应用程序将不支持拆分视图,屏幕方向控制逻辑与上述 iPhone 相同。

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

  • 支持的界面方向 (iPad)
  • 支持的界面方向
  • 用户界面需要全屏

如果您尝试通过Project->Target->General->Device Orientation进行设置会令人困惑:即使Device设置为UniverseiPad 中的设置仍然有效。


Bas*_*CAD 16

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

- (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;
}
Run Code Online (Sandbox Code Playgroud)

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

斯威夫特3:

在UINavigationController子类中执行此操作

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

override var shouldAutorotate: Bool {
        return self.topViewController?.shouldAutorotate ?? false
    }
Run Code Online (Sandbox Code Playgroud)

如果您不想要子类,请 从Matt的答案中获取更新:

第一:让你的viewController成为navigationController的委托 viewDidLoad

self.navigationController?.delegate = self
Run Code Online (Sandbox Code Playgroud)

然后声明UIViewController扩展以响应委托方法,如下所示:

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