iOS 6:如何将某些视图限制为纵向视图,并允许其他视图旋转?

iOS 6:如何将某些视图限制为纵向视图,并允许其他视图旋转?,ios,iphone,ios6,autorotate,Ios,Iphone,Ios6,Autorotate,我有一个iPhone应用程序,它使用一个UINavigationController来呈现一个深入的界面:首先是一个视图,然后是另一个视图,最多四个层次。我希望前三个视图限制为纵向,并且只允许最后一个视图旋转为横向。当从第四个视图返回到第三个视图时,第四个视图是横向的,我希望所有的东西都旋转回到纵向 在iOS 5中,我只是在每个视图控制器中定义了shouldAutorotateToInterfaceOrientation:,以返回允许方向的YES。所有操作如上所述,包括返回到纵向,即使设备从视图

我有一个iPhone应用程序,它使用一个
UINavigationController
来呈现一个深入的界面:首先是一个视图,然后是另一个视图,最多四个层次。我希望前三个视图限制为纵向,并且只允许最后一个视图旋转为横向。当从第四个视图返回到第三个视图时,第四个视图是横向的,我希望所有的东西都旋转回到纵向

在iOS 5中,我只是在每个视图控制器中定义了
shouldAutorotateToInterfaceOrientation:
,以返回允许方向的YES。所有操作如上所述,包括返回到纵向,即使设备从视图控制器4返回到3时保持横向

在iOS 6中,所有视图控制器都会旋转到横向,打破了原本不需要的方向。iOS 6发行说明说

更多的责任转移到应用程序和应用程序代表身上。现在,iOS容器(如
UINavigationController
)不会咨询其子容器以确定它们是否应该自动旋转。[…]每当设备旋转或每当视图控制器显示为全屏模式显示样式时,系统都会向最顶端的全屏视图控制器(通常为根视图控制器)询问其支持的界面方向。此外,仅当此视图控制器从其
shouldAutorotate
方法返回YES时,才会检索支持的方向。[…]系统通过将应用程序的
supportedInterfaceOrientionsforWindow:
方法返回的值与最顶端的全屏控制器的
supportedInterfaceOrientions
方法返回的值相交来确定是否支持方向

因此,我对
UINavigationController
进行了子类化,为我的
MainNavigationController
提供了一个布尔属性
landscapeOK
,并使用该属性返回
支持的接口方向中允许的方向。然后,在我的每个视图控制器的
视图中将出现:
方法中,我有这样一行

    [(MainNavigationController*)[self navigationController] setLandscapeOK:YES];
告诉my
MainNavigationController
所需的行为

问题来了:如果我现在在纵向模式下导航到第四个视图,并将手机翻转过来,它会旋转到横向。现在,我按下后退按钮返回到我的第三个视图,它应该只工作于纵向。但它不会旋转回来。我该怎么做

我试过了

    [[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationPortrait]

在我的第三个视图控制器的
视图中,将出现
方法,但它不起任何作用。这是一个错误的调用方法还是一个错误的调用位置,或者我应该以完全不同的方式实现整个过程?

我想对我自己的问题给出一个部分答案。我发现在我的第三个
UIViewController
viewwillbeen
方法中使用的以下代码行可以工作:

[[UIDevice currentDevice] 
      performSelector:NSSelectorFromString(@"setOrientation:") 
           withObject:(id)UIInterfaceOrientationPortrait];
但我真的不喜欢这个解决方案。它使用一种技巧来分配只读属性,根据苹果的文档,该属性表示设备的物理方向。这就像告诉iPhone跳转到用户手中的正确方向


我很想把它留在我的应用程序中,因为它很简单。但是感觉不对,所以我想把这个问题留给一个干净的解决方案。

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

- (NSUInteger)supportedInterfaceOrientations
{
    return UIInterfaceOrientationMaskPortrait;
}

只返回你想要的方向

我也遇到了同样的问题,找到了适合我的解决方案。 要使其正常工作,仅在UINavigationController中实现支持的接口方向
(NSUInteger)是不够的。 您还需要在您的控制器#3中实现此方法,它是在弹出控制器#4后第一个仅为纵向的方法。 因此,我的UINavigationController中有以下代码:

- (BOOL)shouldAutorotate
{
    return YES;
}

- (NSUInteger)supportedInterfaceOrientations
{
    if (self.isLandscapeOK) {
        // for iPhone, you could also return UIInterfaceOrientationMaskAllButUpsideDown
        return UIInterfaceOrientationMaskAll;
    }
    return UIInterfaceOrientationMaskPortrait;
}
- (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];
}
在视图控制器#3中,添加以下内容:

- (NSUInteger)supportedInterfaceOrientations
{
    return UIInterfaceOrientationMaskPortrait;
}
您不需要向视图控制器1、2和4添加任何内容。
这对我很有用,我希望它能帮助你。

添加一个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;
}

这些方法覆盖导航控制器方法

这是我在ios 6.0中用于方向支持的方法

-(BOOL)shouldAutorotate{
    return YES;
}  

 - (NSUInteger)supportedInterfaceOrientations{
    return UIInterfaceOrientationMaskAll;
}


- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation{  
  return UIInterfaceOrientationPortrait;
}

在看了无数类似问题的每个答案之后,没有一个答案对我有用,但它们确实给了我一些想法。以下是我最终解决问题的方式:

首先,确保项目目标中支持的界面方向包含旋转视图所需的所有方向

接下来,对UINavigationController进行分类(因为苹果公司说不要将其子分类):

将您希望能够旋转的类别和视图控制器(我称之为
RotatingViewController
)导入到最高级别的视图控制器,该视图控制器应包含导航控制器。在该视图控制器中,实现
应自动旋转
,如下所示。请注意,这不应是要旋转的同一视图控制器

-(BOOL)shouldAutorotate {

    BOOL shouldRotate = NO;

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

    return shouldRotate;
}
最后,在
旋转视图控制器
中,实现
应自动旋转
支持的界面方向
,如下所示:

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

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

需要这样做的原因是,iOS 6将旋转控制权交给根视图控制器,而不是俯视图控制器。如果希望单个视图的旋转行为不同于堆栈中的其他视图,则需要在根视图控制器中为其编写一个特定的案例。

如果只想强制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;
    }
}

这可能不适用于所有人,但
[(MainNavigationController*)[self navigationController] setLandscapeOK:YES];
- (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;
    }
}
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(...) {
    ...
}
- (void)back {
    self.isLandscapeOK = self.previousVCLandscapeOK;
    self.previousVCLandscapeOK = NO;
    [self popViewControllerAnimated:YES];
}
@property (nonatomic) BOOL isLandscapeOK;
@property (nonatomic) BOOL previousVCLandscapeOK;
- (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];
}
-(NSUInteger)supportedInterfaceOrientations
{
    UIViewController *topMostViewController = [[Utils getAppDelegate] appNavigationController].topViewController;
    if ([topMostViewController isKindOfClass:[SVWebViewController class]]) {
        return UIInterfaceOrientationMaskAllButUpsideDown;
    }
    return UIInterfaceOrientationMaskPortrait;
}
- (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];
}
-(BOOL)shouldAutorotate
{
    return YES;
}
-(UIInterfaceOrientationMask)supportedInterfaceOrientations{
return UIInterfaceOrientationMaskPortrait;
}
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
    }
}
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]
    }
}