【问题标题】:iOS 8 UIActionSheet ignores view controller supportedInterfaceOrientations and shouldAutorotateiOS 8 UIActionSheet 忽略视图控制器 supportInterfaceOrientations 和 shouldAutorotate
【发布时间】:2014-11-07 06:33:01
【问题描述】:

我有一个通过 plist 文件配置为支持纵向、横向左侧和横向右侧方向的应用程序(即 UISupportedInterfaceOrientations 设置为 UIInterfaceOrientationPortrait、UIInterfaceOrientationLandscapeLeft 和 UIInterfaceOrientationLandscapeRight)。但我已将支持的方向限制为仅在视图控制器内进行纵向显示。如果我在视图控制器的视图上显示 UIActionSheet,然后旋转设备,则 UIActionSheet 将旋转到新方向。这只发生在运行 iOS 8 (GM Seed) 的设备上。

我希望 UIActionSheet 遵循包含视图控制器的规则而不是旋转。想法?

我不希望这种情况发生:

UIViewController 示例代码:

- (IBAction)onTouch:(id)sender
{
    UIActionSheet * actionSheet = [[UIActionSheet alloc] initWithTitle:@"hi"
                                                       delegate:nil
                                              cancelButtonTitle:@"Cancel"
                                         destructiveButtonTitle:nil
                                              otherButtonTitles:@"Open", nil];

    [actionSheet showInView:self.view];
}

#pragma mark - Rotation methods

- (BOOL)shouldAutorotate
{
    return NO;
}

- (NSUInteger)supportedInterfaceOrientations
{
    return UIInterfaceOrientationMaskPortrait;
}

【问题讨论】:

    标签: ios rotation orientation ios8 uiactionsheet


    【解决方案1】:

    被告知 UIAlertController 在 iOS 8 中取代了 UIActionSheet。

    “新的 UIAlertController 类取代了 UIActionSheet 和 UIAlertView 类,成为在您的应用中显示警报的首选方式。”

    https://developer.apple.com/library/prerelease/ios/releasenotes/General/WhatsNewIniOS/Articles/iOS8.html

    UIAlertController * alertController = [UIAlertController alertControllerWithTitle:@"hi"
                                                                              message:nil
                                                                       preferredStyle:UIAlertControllerStyleActionSheet];
    
    [alertController addAction:[UIAlertAction actionWithTitle:@"Open"
                                                      style:UIAlertActionStyleDefault
                                                    handler:^(UIAlertAction *action) {
                                                       // open something
                                                    }]];
    
    [alertController addAction:[UIAlertAction actionWithTitle:@"Cancel"
                                                      style:UIAlertActionStyleCancel
                                                    handler:nil]];
    
    [self presentViewController:alertController animated:YES completion:nil];
    

    【讨论】:

    • 当然,有一种新的“首选”方式,但为什么仅仅因为引入了一种新方式就改变/破坏旧的工作功能呢?这种新方法是获得原始行为的唯一方法吗?
    • 不,因为 iOS7 用户仍然需要处理旧的警报/表格。显然是一个需要修复的错误。
    • 在 iOS7 上,旧的 UIActionSheet 不会出现旋转问题。在 iOS7 及更早版本上使用 UIActionSheet。在 iOS8 和更新版本上使用 UIAlertController。检查 NSClassFromString(@"UIAlertController") 以确定要使用的代码。
    • @ChitraKhatri 我在上面的帖子中添加了一个如何使用 UIAlertController 的示例。
    【解决方案2】:

    我在 iOS 8 上遇到了类似的问题,如果您现在想坚持使用 UIAlertView 和 UIActionSheet,而不是迁移到 UIAlertController,找到了一个可能会有所帮助的解决方法。

    我的应用允许横向和纵向,但仅限于选定的视图。大多数时候它只允许肖像。我希望 UIAlertView 和 UIActionSheet 只显示纵向(因为它们所在的视图只允许纵向)。

    不幸的是,在 iOS 8 中,警报和操作表现在会旋转,忽略窗口根视图控制器的 shouldAutorotate 方法。即使警报旋转,警报下方的视图和状态栏也会在纵向中保持可见。如果警报需要输入,键盘也会保持纵向,所以它真的没有吸引力。

    我正要放弃,但终于找到了一些有用的东西,即使它并不理想。将其放入您的应用程序委托中,并根据需要进行调整。我期待更好的解决方案(可能只是使用新类)。这里的字符串比较显然是蹩脚的,这将覆盖您在 Info.plist 中设置为支持方向的任何内容。至少它是继续的事情......

    -(NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window
    {
        NSString *viewControllerClassName = [NSString stringWithUTF8String:object_getClassName(window.rootViewController)];
        if ([viewControllerClassName isEqualToString:@"_UIAlertShimPresentingViewController"])   {
            return UIInterfaceOrientationMaskPortrait;
        }
        else {
            return UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskLandscapeLeft | UIInterfaceOrientationMaskLandscapeRight;
        }
    }
    

    在此处阅读有关此代表的更多信息:

    https://developer.apple.com/library/prerelease/iOS/documentation/UIKit/Reference/UIApplicationDelegate_Protocol/index.html#//apple_ref/occ/intfm/UIApplicationDelegate/application:supportedInterfaceOrientationsForWindow:

    【讨论】:

    • 这是否会导致 App Store 拒绝,因为它使用的是私有类?
    • 如果您担心“_UI...”,请尝试以下 user3750435 的变体。 “使用”类名来确定何时不旋转不是最安全的事情,但不应该是违规行为,因为它没有调用类的任何方法/属性。作为另一种选择,您可以将窗口与您自己已知的窗口进行匹配。我的用途仅限于企业,因此没有被拒绝的风险。
    【解决方案3】:

    这是我基于 Busrod 的解决方案的解决方法,并进行了一些修改,因为我在 UIActionSheet 中使用他的解决方法时遇到了一些问题:

    -(UIInterfaceOrientationMask)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window
    {
        UIViewController *presentedViewController = window.rootViewController.presentedViewController;
        if (presentedViewController) {
            if ([presentedViewController isKindOfClass:[UIActivityViewController class]] || [presentedViewController isKindOfClass:[UIAlertController class]]) {
                return UIInterfaceOrientationMaskPortrait;
            }
        }
        return UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskLandscapeLeft | UIInterfaceOrientationMaskLandscapeRight;
    }
    

    【讨论】:

    • 是的,这行得通。谢谢!如果可用,我选择使用新的 UIAlertController。块的使用非常好,我很快就会放弃对 iOS 7 的支持。
    • 肖像倒置失败。
    • 如果你想支持倒置,返回 UIInterfaceOrientationMaskAll 代替。
    • SLComposeViewController 也有同样的问题,也可以在 if 语句中添加
    【解决方案4】:

    添加到@user3750435 的答案

    由于 OP 已经在 Info.plist 中定义了他/她想要的旋转遮罩,我们不需要在这里重新定义遮罩。 UIApplication 可以通过以下方式将这些口罩归还给我们 supportedInterfaceOrientationsForWindow:。因此,该方法可以像这样更简单:

    -(NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window
    {
        UIViewController *presentedViewController = window.rootViewController.presentedViewController;
        if (presentedViewController) {
            if ([presentedViewController isKindOfClass:[UIActivityViewController class]] || [presentedViewController isKindOfClass:[UIAlertController class]]) {
                return UIInterfaceOrientationMaskPortrait;
            }
        }
        return [application supportedInterfaceOrientationsForWindow:window];
    }
    

    【讨论】:

      【解决方案5】:

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

      UIViewController *presentedViewController = window.rootViewController.presentedViewController;
      if (presentedViewController) {
          if ([presentedViewController isKindOfClass:[UIActivityViewController class]] || [presentedViewController isKindOfClass:[UIAlertController class]]) {
              return UIInterfaceOrientationMaskPortrait;
          }
      }
      return UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskLandscapeLeft | UIInterfaceOrientationMaskLandscapeRight;
      

      }

      感谢这对我有用

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2012-10-01
        • 2014-09-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多