iOS 6中:如何限制一些看法肖像,并允许其他旋转?(iOS 6: How do I restric

2019-06-18 09:15发布

我有一个使用一个iPhone应用程序UINavigationController呈现向下钻取界面:一是一种观点,然后又多达四层深。 我想第一个三个视图限制为纵向,只有最后一个视图应该允许旋转为横向。 当从第四视图返回到第三和第四个观点是在横向方向我想要的一切转回肖像。

在IOS 5 I简单地定义shouldAutorotateToInterfaceOrientation:在每个我的视图控制器的为允许取向返回YES。 如上述那样,包括返回到即使从视图控制器#4返回至#3时被关在横向定向的设备肖像一切工作。

在iOS 6中的所有视图控制器旋转为横向,打破那些被无意。 在iOS 6的发布说明说

更多的责任正在向应用程序和应用程序的委托。 现在,iOS的容器(如UINavigationController )不咨询自己的孩子,以确定他们是否应该自动旋转。 [...]的系统要求它的支持的接口方向最上面的全屏幕视图控制器(典型根视图控制器)每当设备旋转或每当一个视图控制器呈现全屏幕模式呈现样式。 此外,支撑取向检索仅当此视图控制器从其返回YES shouldAutorotate方法。 [...]系统确定的方位是否是由交叉的由应用的返回的值支持supportedInterfaceOrientationsForWindow:与由所述返回的值方法supportedInterfaceOrientations最顶部的全屏幕控制器的方法。

所以我子类UINavigationController ,给我MainNavigationController布尔属性landscapeOK并用它来作为回报,允许取向supportedInterfaceOrientations 。 然后,在我的每一个视图控制器viewWillAppear:方法我有一个这样的行

    [(MainNavigationController*)[self navigationController] setLandscapeOK:YES];

告诉我MainNavigationController所期望的行为。

问题来了:如果我现在转到我在纵向模式下第四视图并开启手机在它旋转为横向。 现在我按后退按钮返回到我这应该只是工作肖像第三种观点。 但它不转回。 我该如何利用它做些什么?

我试过了

    [[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationPortrait]

viewWillAppear我的第三个视图控制器的方法,但它不会做任何事情。 这是错误的方法来调用也许错了地方调用它,或者我应该是在一个完全不同的方式实现了整个事情?

Answer 1:

我有同样的问题,并发现适合我的解决方案。 为了使它工作,这是不足以实现- (NSUInteger)supportedInterfaceOrientations在你的UINavigationController。 您还需要在你的控制器#3,这是变为纵向只弹出控制器#4后,第一个实现此方法。 所以,我在我的UINavigationController下面的代码:

- (BOOL)shouldAutorotate
{
    return YES;
}

- (NSUInteger)supportedInterfaceOrientations
{
    if (self.isLandscapeOK) {
        // for iPhone, you could also return UIInterfaceOrientationMaskAllButUpsideDown
        return UIInterfaceOrientationMaskAll;
    }
    return UIInterfaceOrientationMaskPortrait;
}

在视图控制器#3,添加以下内容:

- (NSUInteger)supportedInterfaceOrientations
{
    return UIInterfaceOrientationMaskPortrait;
}

你不需要任何东西添加到您的视图控制器#1,#2,#4。 这对我的作品,我希望它会帮助你。



Answer 2:

添加CustomNavigationController

覆盖它这些方法:

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

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

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

现在,添加所有方向的plist中

在视图控制器仅添加所需的项目:

-(BOOL)shouldAutorotate
{
    return YES;
}

-(NSUInteger)supportedInterfaceOrientations
{
    return UIInterfaceOrientationMaskPortrait;
}

这些方法重写导航控制器方法



Answer 3:

通过在SO无数类似的问题每一个答案,寻找后,没有一个答案为我工作,但他们给我的一些想法。 以下是我最终解决问题:

首先,确保你支持的界面取向在项目的目标包含你想为你的旋转视图中的所有方向。

接下来,使一类UINavigationController (因为苹果说不是它的子类):

@implementation UINavigationController (iOS6AutorotationFix)

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

@end

导入类别和要能够(我称之为旋转视图控制器RotatingViewController )到你的最高水平视图控制器,它应该包含你的导航控制器。 在该视图中的控制器,实现shouldAutorotate如下。 请注意,这不应该是你想同向旋转视图控制器。

-(BOOL)shouldAutorotate {

    BOOL shouldRotate = NO;

    if ([navigationController.topViewController isMemberOfClass:[RotatingViewController class]] ) {
        shouldRotate = [navigationController.topViewController shouldAutorotate];
    }

    return shouldRotate;
}

最后,在你的RotatingViewController ,实现shouldAutorotatesupportedInterfaceOrientations如下:

-(BOOL)shouldAutorotate {
    // Preparations to rotate view go here
    return YES;
}

-(NSUInteger)supportedInterfaceOrientations {
    return UIInterfaceOrientationMaskAllButUpsideDown; // or however you want to rotate
}

你需要做的原因是因为iOS 6中给出了旋转控制到根视图控制器,而不是俯视图controlller。 如果您希望个人观点自转表现比在堆栈中的其他意见不同,你需要在根视图控制器写入特定情况下它。



Answer 4:

我没有足够的信誉评论@布赖恩的答案,所以我会在这里为我的笔记。

布赖恩提到,iOS6的给旋转控制到RootViewController的 - 这可能不仅是一个UINavigationController作为提及,但也是一个的UITabBarController,这对我来说是。 我的结构是这样的:

  • 的UITabBarController
    • UINavigationController的
      • UIViewControllers ...
    • UINavigationController的
      • UIViewControllers ...

所以我第一次添加的方法,在自定义的UITabBarController,然后在自定义的UINavigationController,然后最后在具体的UIViewController。

从的UITabBarController和UINavigationController的实施例:

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

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

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation {
    return [self.viewControllers.lastObject shouldAutorotateToInterfaceOrientation:toInterfaceOrientation];
}

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


Answer 5:

我想给了部分答案,以我自己的问题。 我发现下面的一行代码,在使用viewWillAppear我的第三个方法UIViewController ,工作:

[[UIDevice currentDevice] 
      performSelector:NSSelectorFromString(@"setOrientation:") 
           withObject:(id)UIInterfaceOrientationPortrait];

但我真的不喜欢这种解决方案。 它使用的是特技分配给根据苹果文档其表示所述装置的物理取向的只读属性。 这就像告诉iPhone跳转到正确的方向在用户的手中。

我很动心离开这个在我的应用程序,因为它只是工作。 但感觉不对,所以我想离开开了清晰的解决方案的问题。



Answer 6:

这是我使用的IOS 6.0定向支持

-(BOOL)shouldAutorotate{
    return YES;
}  

 - (NSUInteger)supportedInterfaceOrientations{
    return UIInterfaceOrientationMaskAll;
}


- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation{  
  return UIInterfaceOrientationPortrait;
}


Answer 7:

作为,这是一个高度看线程。 我想我要补充什么,我认为这是最简单的答案。 这适用于iOS8上最多

-(BOOL)shouldAutorotate
{
    return YES;
}

-(UIInterfaceOrientationMask)supportedInterfaceOrientations{
return UIInterfaceOrientationMaskPortrait;
}

而已。 请享用!

哦,我的ViewControllers嵌入导航控制器,但我并不需要继承或配置以任何方式。



Answer 8:

这可能不是适合每一个人,但它为我的伟大工程。 取而代之的实施...

[(MainNavigationController*)[self navigationController] setLandscapeOK:YES];

在viewWillAppear中所有我的控制器,我决定通过重写集中我的UINavigationController子类的里面这个过程UINavigationControllerDelegate方法navigationController:willShowViewController:animated:

- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated {

    self.previousVCLandscapeOK = self.isLandscapeOK; // Store the current VC's orientation preference before pushing on the new VC so we can set this again from within the custom "back" method
    self.isLandscapeOK = NO; // Set NO as default for all VC's
    if ([viewController isKindOfClass:[YourViewController class]]) {
        self.isLandscapeOK = YES;
    }
}

我发现一个弹出VC关闭导航堆栈时,此委托方法不会被调用。 这不是我的问题,因为我从我的UINavigationController子类中处理后的功能,这样我可以设置特定VC的像这样适当的导航栏按钮和操作...

if ([viewController isKindOfClass:[ShareViewController class]]) {

    UIButton* backButton = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, 57, 30)];
    [backButton setImage:[UIImage imageNamed:@"back-arrow"] forState:UIControlStateNormal];
    [backButton addTarget:self action:@selector(back) forControlEvents:UIControlEventTouchUpInside];
    UIBarButtonItem* backButtonItem = [[UIBarButtonItem alloc] initWithCustomView:backButton];
    viewController.navigationItem.leftBarButtonItem = backButtonItem;

    UIImageView* shareTitle = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"share-title"]];
    [shareTitle setContentMode:UIViewContentModeScaleAspectFit];
    [shareTitle setFrame:CGRectMake(0, 0, shareTitle.frame.size.width - 10, shareTitle.frame.size.height - 10)];
    viewController.navigationItem.titleView = shareTitle;

} else if(...) {
    ...
}

这里是我的什么back法样子来处理弹出的VC出栈,并设置适当的轮换偏好...

- (void)back {
    self.isLandscapeOK = self.previousVCLandscapeOK;
    self.previousVCLandscapeOK = NO;
    [self popViewControllerAnimated:YES];
}

所以,你可以看到,基本上所有正在发生的事情是我第一次设置我的两个属性...

@property (nonatomic) BOOL isLandscapeOK;
@property (nonatomic) BOOL previousVCLandscapeOK;

navigationController:willShowViewController:animated:这将决定支撑取向是VC是要被呈现内的东西。 当弹出一个VC,我自定义的“后退”方法被调用,然后我的isLandscapeOK设置什么经previousVCLandscapeOK值存储。

正如我所说的,这可能并不适用于每个人,但我的伟大工程,我不担心将代码添加到我的每个视图控制器,我能够保持它的所有集中在UINavigationController的子类。

希望这可以帮助别人,因为它没有我。 谢谢,杰里米。



Answer 9:

转到你Info.plist文件并进行更改



Answer 10:

要强制的iOS 6应用人像只有那么你可以添加以下方法UIViewController子类

- (BOOL)shouldAutorotate {
    if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
        return YES;
    } else {
        return NO;
    }
}


- (NSUInteger)supportedInterfaceOrientations {
    if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
        return UIInterfaceOrientationMaskAll;
    } else {
        return UIInterfaceOrientationMaskPortrait;
    }
}


Answer 11:

我想有我所有VC锁定为纵向,除了一个。 这是对我工作。

  1. 添加在plist文件的所有方位的支持。
  2. 在根视图控制器,检测在窗口的顶部的那种视图控制器这就是和在supportedInterfaceOrientations方法相应地设置应用程序的方向。 例如,我需要我的应用程序只有在网页视图是在堆栈的顶部旋转。 下面是我在rootVC补充说:

     -(NSUInteger)supportedInterfaceOrientations { UIViewController *topMostViewController = [[Utils getAppDelegate] appNavigationController].topViewController; if ([topMostViewController isKindOfClass:[SVWebViewController class]]) { return UIInterfaceOrientationMaskAllButUpsideDown; } return UIInterfaceOrientationMaskPortrait; } 


Answer 12:

我没有足够的信誉来回答下@micmdk答复@Ram提问,所以我会在这里为我的笔记。

当您使用的UITabBarController,试图改变self.viewControllers.lastObject在@ micmdk的代码self.selectedViewController是这样的:

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

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

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation {
    return [self.selectedViewController shouldAutorotateToInterfaceOrientation:toInterfaceOrientation];
}

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


Answer 13:

您可以实现并重写shouldAutorotate()和VAR supportedInterfaceOrientations在所有应该在不同的方向而不是在你的应用程序的PLIST上定义的呈现你的视图控制器类。

然而,在平凡的用户界面可能会面对的问题,将其添加在几十个班级,你不想让所有的人都支持它的几种常见(MyBaseTableViewController,MyBaseNavigationController和MyBaseTabBarController)的子类。

既然你不能直接覆盖在UIViewController的那些方法/ VAR,你可以做它的子类通常是一样的UITableViewController,UINavigationController的和你的UITabBarController的基类。

所以,你可以实现一些扩展,仍然设置MyPreciousViewController在不同的方向比其他所有类似这样的雨燕4代码片段显示:

extension UITableViewController {
    override open var supportedInterfaceOrientations: UIInterfaceOrientationMask {

    if let last = self.navigationController?.childViewControllers.last,
        last != self {
            return last.supportedInterfaceOrientations
    } else {
        return [.portrait]
    }
    }
}

extension MyPreciousViewController {
    override open var supportedInterfaceOrientations: UIInterfaceOrientationMask {

    return [.portrait,.landscape]
    }
}


extension UINavigationController {
    override open var supportedInterfaceOrientations: UIInterfaceOrientationMask {

        return [.portrait]
    }
}


extension UITabBarController {
    override open var supportedInterfaceOrientations: UIInterfaceOrientationMask {

        return [.portrait]
    }
}


Answer 14:

我已经解决了同一类问题。

如果您使用的是UINavigationController推视图控制器,你必须设置下面的方法。

extension UINavigationController{

    override open var shouldAutorotate: Bool {

        if topViewController != nil && (topViewController?.isKind(of: LogInViewController.self))!
        {
            return true
        }
        return false
    }

    override open var supportedInterfaceOrientations: UIInterfaceOrientationMask {

        if topViewController != nil && (topViewController?.isKind(of: LogInViewController.self))!
        {
            return .portrait
        }
        return .landscapeRight

    }
    override open var preferredInterfaceOrientationForPresentation: UIInterfaceOrientation {

        if topViewController != nil && (topViewController?.isKind(of: LogInViewController.self))!
        {
            return .portrait
        }
        return .landscapeRight
    }
}

在地方的LoginViewController使用它UIViewController你想展示。 在我的情况,我想显示LoginViewControllerPortrait模式等ViewControllerslandscape模式。



Answer 15:

请使用以下方法来解决这个问题

- (NSUInteger)supportedInterfaceOrientations
{
    return UIInterfaceOrientationMaskPortrait;
}

只返回你想要的方向!



文章来源: iOS 6: How do I restrict some views to portrait and allow others to rotate?