【问题标题】:Force iOS orientation to landscape on one modal view controller在一个模式视图控制器上强制 iOS 方向为横向
【发布时间】:2025-07-01 04:45:02
【问题描述】:

我有一个支持 iPad 和 iPhone 的通用应用程序。在 iPad 上,我支持所有方向,而在 iPhone 上,我只支持纵向。

我希望一个视图控制器(以模态方式显示)在 iPhone 上运行时以设备所在的任何方向显示。我看过许多建议使用 -(NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window 应用程序委托的教程和 SO 帖子方法,这在旋转模态视图控制器方面似乎工作得很好。但是,当我在横向模式下关闭模式视图时,整个应用程序仍然是横向的。

理想情况下,一旦模式视图被关闭,应用程序应立即返回纵向模式。

经过调查,在关闭视图控制器后似乎没有调用-(NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window 回调,我无法弄清楚原因。

我玩过示例应用程序here,当关闭视图控制器时会触发回调,我不知道为什么。我能看到的唯一区别是我的视图层次结构要复杂得多,而且我显示的是导航控制器而不是显式视图控制器,但我看不出这应该如何影响回调。

有什么想法可以解决这个问题吗?

谢谢

【问题讨论】:

    标签: ios objective-c iphone modalviewcontroller uiinterfaceorientation


    【解决方案1】:

    您可以尝试使用此方法(在应用商店构建中工作):

    [[UIDevice currentDevice] performSelector:@selector(setOrientation:)
                                   withObject:(__bridge id)((void*)UIInterfaceOrientationPortrait)];
    

    【讨论】:

    • 谢谢,与@Igor.Mursa 建议的解决方法一样有效。
    【解决方案2】:

    在应用代理中:

      - (UIInterfaceOrientationMask)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window 
    {
    // Get topmost/visible view controller
        UIViewController *currentViewController = [self topViewController];
    
    //Hire check your needed device ore other things you need
        if ( UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone )
        { 
         //device is iphone
             if ([currentViewController respondsToSelector:@selector(canRotate)]) 
             {
                // Unlock landscape view orientations for this view controller
                return UIInterfaceOrientationMaskAll;
             }
             return UIInterfaceOrientationMaskPortrait;
        }  
        else
        //device Ipad
        return UIInterfaceOrientationMaskAll;  
    }
    
    }
    - (UIViewController*)topViewController {
    return [self topViewControllerWithRootViewController:[UIApplication sharedApplication].keyWindow.rootViewController];
    }
    
    - (UIViewController*)topViewControllerWithRootViewController:(UIViewController*)rootViewController {
    if ([rootViewController isKindOfClass:[UITabBarController class]]) {
        UITabBarController* tabBarController = (UITabBarController*)rootViewController;
        return [self topViewControllerWithRootViewController:tabBarController.selectedViewController];
    } else if ([rootViewController isKindOfClass:[UINavigationController class]]) {
        UINavigationController* navigationController = (UINavigationController*)rootViewController;
        return [self topViewControllerWithRootViewController:navigationController.visibleViewController];
    } else if (rootViewController.presentedViewController) {
        UIViewController* presentedViewController = rootViewController.presentedViewController;
        return [self topViewControllerWithRootViewController:presentedViewController];
    } else {
        return rootViewController;
    }
    }
    

    在需要旋转的视图中确保实现

      - (void)canRotate { }
    

    这将允许您仅旋转 iPhone 设备所需的视图。

    我在旧的 * 帖子的帮助下得到了这段代码,但我现在找不到它的链接

    【讨论】:

    • 感谢您的代码。我刚刚尝试过这个,但同样的问题存在。我可以旋转视图,但如果我在横向模式下关闭模式,应用程序不会恢复为纵向模式。由于某种原因,我的应用程序在关闭模式后似乎没有调用 supportedInterfaceOrientationsForWindow 方法。你有过这个问题吗?
    • a 确实遇到过这种问题,当时我发现的唯一解决方案是在关闭视图之前以编程方式旋转视图,类似于 [self dismissViewControllerAnimated: YES completion:^{ [self willAnimateRotationToInterfaceOrientation:UIDeviceOrientationPortrait duration:1];}]; ,我不能 100% 确定这段代码是否会工作,我现在写了,我的情况 - 我正在展示一个导航控制器,我在展示之前正在旋转
    • 谢谢。不幸的是,willAnimateRotationToInterfaceOrientation:duration: 在 iOS 8 中已被弃用,所以我不能使用它。当模式视图被关闭并手动调用应用程序委托方法时,我总是可以触发通知。不是最干净的方法。在使用这种方法之前,我会看看是否有任何其他建议或解决方法。
    • NSNumber *value = [NSNumber numberWithInt:UIInterfaceOrientationPortrait]; [[UIDevice currentDevice] setValue:value forKey:@"orientation"]; 试试这样设置怎么样