36

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

信息列表:

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

任何不应被允许旋转的 ViewController:

//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 中进行旋转。

4

9 回答 9

31

如果您的 ViewController 是 UINavigationController 或 UITabBarController 的子级,那么问题就是父级。您可能需要对该父视图控制器进行子类化,只需覆盖您在问题中显示的那些 InterfaceOrientation 方法

编辑:

仅纵向 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
于 2012-09-13T17:27:39.897 回答
27

添加到上面 CSmith 的答案中,UINavigationController 子类中的以下代码允许以我最初期望的方式委托给顶视图控制器:

- (BOOL)shouldAutorotate;
{
    return YES;
}

- (NSUInteger)supportedInterfaceOrientations
{
    if ([[self topViewController] respondsToSelector:@selector(supportedInterfaceOrientations)])
        return [[self topViewController] supportedInterfaceOrientations];
    else
        return [super supportedInterfaceOrientations];
}
于 2012-09-20T06:31:08.177 回答
8

这是 CSmith 方法的另一种选择。

如果您想复制 iOS 6 之前的行为,即导航堆栈/选项卡栏中的所有视图必须就一组允许的方向达成一致,请将其放在您的子类中UITabBarControlleror UINavigationController

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

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

    return orientations;
}
于 2012-10-19T12:21:17.090 回答
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
于 2013-04-04T08:14:51.830 回答
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()
    }
}
于 2015-08-07T19:12:34.993 回答
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];
}
于 2014-07-12T19:57:00.227 回答
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
    }
}
于 2018-05-11T12:36:37.067 回答
-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
于 2014-05-21T20:15:05.687 回答
-2

作为替代选项,如果您想在应用中保留 iOS6 之前的旋转功能:

这是 github 上的一些有用代码,它调整了 iOS6 的方法调用,以便旋转像在 iOS4/iOS4 上一样工作。这真的帮助了我,因为我支持一个真正微观管理其轮换的遗留应用程序。实现 iOS6 所需的更改将是大量工作。感谢发布它的用户。

https://gist.github.com/3725118

于 2012-09-19T17:35:39.037 回答