iOS 6旋转:supportedInterfaceOrientations无效?

36

我在使用iOS 6 SDK时遇到了这个问题:我有一些视图应该被允许旋转(例如,一个视频视图),而另一些则不应该。 现在我明白了我必须检查应用程序的 Info.plist 中的所有方向,然后在每个ViewController中进行筛选,决定应该发生什么。但它并没有起作用!应用程序总是旋转到在Info.plist中给出的方向。

Info.plist:

<key>UISupportedInterfaceOrientations</key>
    <array>
        <string>UIInterfaceOrientationPortrait</string>
        <string>UIInterfaceOrientationLandscapeLeft</string>
        <string>UIInterfaceOrientationLandscapeRight</string>
    </array>

任何不应该被允许旋转的视图控制器:

//deprecated
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}

- (NSUInteger)supportedInterfaceOrientations{
return UIInterfaceOrientationMaskPortrait;
}

观察:应用程序在横向和纵向方向上旋转。有什么想法或我做错了什么吗?

谢谢,马克

编辑:我的最新发现也表明,如果您想在应用程序中某个时刻进行旋转,则必须在项目设置或Info.plist中激活所有四个旋转方向。另一种选择是覆盖。

- (NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window

在您的AppDelegate中,它覆盖了Info.plist。 现在不再可能仅在Info.plist中设置Portrait,然后通过覆盖shouldAutorotateToInterfaceOrientation或supportedInterfaceOrientations在某些ViewController中进行旋转。


这是受NDA保护的内容,请在苹果开发者论坛上发布,我可以提供帮助。 - Ben Clayton
这样做会更好吗?我猜现在没有人会再关心侵犯保密协议了... - stk
这仍然是一份保密协议,而且我猜这是一个常见的问题,在开发论坛上已经得到了充分的回答。 - wattson12
9个回答

31

如果您的视图控制器是UINavigationController或UITabBarController的子控制器,则应该查看父控制器。您可能需要创建一个子类来覆盖那些与接口方向相关的方法,就像您在问题中展示的那样。

编辑:

以只支持竖屏的TabBarController为例

           @interface MyTabBarController : UITabBarController
            {
            }
            @end

            @implementation MyTabBarController

            // put your shouldAutorotateToInterfaceOrientation and other overrides here        
            - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
                return (interfaceOrientation == UIInterfaceOrientationPortrait);
            }

            - (NSUInteger)supportedInterfaceOrientations{ 
                return UIInterfaceOrientationMaskPortrait; 
            } 

        @end

4
你不应该忘记 - supportedInterfaceOrientations 方法,因为在 iOS6 中,shouldAutorotate... 已经不再使用了! - stk

27

在CSmith上面的回答中,以下代码在UINavigationController子类中允许代理到顶部视图控制器,以我最初期望的方式工作:

- (BOOL)shouldAutorotate;
{
    return YES;
}

- (NSUInteger)supportedInterfaceOrientations
{
    if ([[self topViewController] respondsToSelector:@selector(supportedInterfaceOrientations)])
        return [[self topViewController] supportedInterfaceOrientations];
    else
        return [super supportedInterfaceOrientations];
}

5
这个功能完美运作!!为什么苹果IOS SDK没有做这个呢? :( - flypig
5
@flypig,以前情况是这样的。苹果iOS SDK以前的行为完全如此。随着iOS 6的推出,他们无明显原因地将其更改为新系统。 - David Hay

8

这是对CSmith方法的另一种替代方案。

如果您想复制iOS 6之前的行为,即导航栈/选项卡栏中的所有视图都必须同意一组允许的方向,则将以下内容放入UITabBarControllerUINavigationController子类:

- (NSUInteger)supportedInterfaceOrientations
{
    NSUInteger orientations = [super supportedInterfaceOrientations];

    for (UIViewController *controller in self.viewControllers)
        orientations = orientations & [controller supportedInterfaceOrientations];

    return orientations;
}

2
尝试添加此类别:
@interface UINavigationController(InterfaceOrientation)

@end

@implementation UINavigationController(InterfaceOrientation)

- (NSUInteger) supportedInterfaceOrientations {
    if (self.viewControllers.count > 0)
        return [[self.viewControllers objectAtIndex:0] supportedInterfaceOrientations];
    else
        return UIInterfaceOrientationMaskAll;
}

@end

非常好用,任何子类都可以!谢谢!但我更喜欢使用数组中最后一个视图控制器,因为它当前正在显示。 - HotJard

1

如果您正在使用UINavigationController和Swift,则可以将此扩展添加到您的项目中。之后,导航控制器将委托其子控制器来进行控制。

extension UINavigationController {
    override public func supportedInterfaceOrientations()
    -> UIInterfaceOrientationMask {
        if let ctrl = topViewController {
            return ctrl.supportedInterfaceOrientations()
        }
        return super.supportedInterfaceOrientations()
    }

    override public func shouldAutorotate() -> Bool {
        if let ctrl = topViewController {
            return ctrl.shouldAutorotate()
        }
        return super.shouldAutorotate()
    }
}

这对我有效。我已经添加了Swift 4版本如下。 - Harikrishna Pai

0

@Alvivi的答案已更新至Swift 4

extension UINavigationController {

    // Look for the supportedInterfaceOrientations of the topViewController
    // Otherwise, viewController will rotate irrespective of the value returned by the ViewController
    override open var supportedInterfaceOrientations: UIInterfaceOrientationMask {
        if let ctrl = self.topViewController {
            return ctrl.supportedInterfaceOrientations
        }
        return super.supportedInterfaceOrientations
    }

    // Look for the shouldAutorotate of the topViewController
    // Otherwise, viewController will rotate irrespective of the value returned by the ViewController
    override open var shouldAutorotate: Bool {
        if let ctrl = self.topViewController {
            return ctrl.shouldAutorotate
        }
        return super.shouldAutorotate
    }
}

0

对于@CSmith和@EvanSchoenberg的进一步补充。

如果您有一些旋转的视图和一些不旋转的视图,您必须创建一个自定义的UITabBarController实例,但仍然让每个UIViewController决定。

- (BOOL)shouldAutorotate;
{
    return YES;
}

- (NSUInteger)supportedInterfaceOrientations
{
    UIViewController * top;
    UIViewController * tab = self.selectedViewController;
    if([tab isKindOfClass:
        ([UINavigationController class])]) {
        top = [((UINavigationController *)tab)
                 topViewController];
    }

    if ([top respondsToSelector:@selector(supportedInterfaceOrientations)])
        return [top supportedInterfaceOrientations];
    else
        return [super supportedInterfaceOrientations];
}

-1

@Shimanski Artem的回答很好,但我认为使用最顶层(当前可见)的控制器是更好的解决方案:

@interface UINavigationController(InterfaceOrientation)

@end

@implementation UINavigationController(InterfaceOrientation)

- (NSUInteger) supportedInterfaceOrientations {
    if (self.viewControllers.count > 0){
        return [[self.viewControllers objectAtIndex:[self.viewControllers count] - 1] supportedInterfaceOrientations];
    }
    return UIInterfaceOrientationMaskAll;
}

@end

-2

如果您想在应用程序中保留 iOS6 之前的旋转功能,这里有一个备选方案:

在 Github 上有一段非常有用的代码,可以交换 iOS6 的方法调用,使旋转功能像在 iOS4/iOS4 上一样工作。这对我来说非常有帮助,因为我正在支持一个真正微观管理其旋转的遗留应用程序。要实现 iOS6 所需的更改需要很多工作。向发布它的用户致敬。

https://gist.github.com/3725118


1
这是一个非常非常糟糕的想法,只是说说而已。 - steipete

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接