UIAlertController:supportedInterfaceOrientations被递归调用

39
当两个弹出窗口一个接一个地出现时,意味着一个弹窗已经出现并且另一个弹窗在其上方,应用程序崩溃了。 我使用了UIAlertController来显示弹窗。这个应用程序只在iOS 9设备上崩溃。 请在这一点上帮助我。
7个回答

76

iOS 9存在一个bug,它无法检索UIAlertControllersupportedInterfaceOrientations。看起来在查找UIAlertControllersupportedInterfaceOrientations时它陷入了无限递归循环(例如跟踪到UIAlertControler -> UIViewController -> UINavigationController -> UITabBarController -> UIAlertController -> ...),而实际上在源代码中没有实现/覆盖UIAlertController:supportedInterfaceOrientations的调用。

在我的解决方案中,我只需添加以下代码:

extension UIAlertController {     
    public override func supportedInterfaceOrientations() -> UIInterfaceOrientationMask {
        return UIInterfaceOrientationMask.Portrait
    }
    public override func shouldAutorotate() -> Bool {
        return false
    }
}

那么UIAlertController将直接返回支持的方向值,而不会出现无限循环。希望能帮到你。

编辑:Swift 3.0.1

extension UIAlertController {
    open override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
        return UIInterfaceOrientationMask.portrait
    }  
    open override var shouldAutorotate: Bool {
        return false
    }
}

2
@Annie,你不应该使用分类重写一个方法,因为无法确定哪个方法会被调用,苹果公司强烈反对这样做。 - Oscar Gomez
3
在Xcode 7和Swift 2.1中,似乎我们需要将supportedInterfaceOrientations返回UIInterfaceOrientationMask而不是Int。这样你也不需要强制转换返回值。 - davidethell
看起来在新的SDK中(截至iOS 10和11),这不再是一个问题。实际上,一旦您将部署目标从iOS 8提高到iOS 9,这里的解决方案会导致问题,例如当应用程序实际处于横向模式时,键盘会从侧面拉起。 - CodeBrew
@CodePlumber 我刚开始在Xcode 9.4.1和iOS 11上遇到了这个问题,所以我认为它还没有被修复。部署目标是iOS 10。 - user1898712
@OscarGomez 我在我的应用程序中覆盖扩展中的方法时遇到了类似的问题。我正在努力寻找苹果文档,以确定我们不应该这样做。你能指点我吗? - dubbeat

16

我的解决方案是针对UIAlertViewController的Objective-C类别。只需在任何使用UIAlertController的类中包含UIAlertController+supportedInterfaceOrientations.h即可。

UIAlertController+supportedInterfaceOrientations.h

//
//  UIAlertController+supportedInterfaceOrientations.h

#import <UIKit/UIKit.h>
@interface UIAlertController (supportedInterfaceOrientations)
@end

UIAlertController+supportedInterfaceOrientations.m

//
//  UIAlertController+supportedInterfaceOrientations.m

#import "UIAlertController+supportedInterfaceOrientations.h"

@implementation UIAlertController (supportedInterfaceOrientations)

#if __IPHONE_OS_VERSION_MAX_ALLOWED < 90000
- (NSUInteger)supportedInterfaceOrientations {
    return UIInterfaceOrientationMaskPortrait;
}
#else
- (UIInterfaceOrientationMask)supportedInterfaceOrientations {
    return UIInterfaceOrientationMaskPortrait;
}
#endif

@end

6
作为对Roland Keesom答案的更新,以下是对我起作用的方法。主要区别在于supportedInterfaceOrientations函数实际上返回的是UIInterfaceOrientationMask而不是Int。
而且,在这个变体中,所有方向都受支持。
extension UIAlertController {

    public override func shouldAutorotate() -> Bool {
        return true
    }

    public override func supportedInterfaceOrientations() -> UIInterfaceOrientationMask {
        return UIInterfaceOrientationMask.All
    }
}

3

我觉得编写扩展似乎是合理的,但在实现时遇到了错误。

覆盖“shouldAutorotate”必须像它覆盖的声明一样可用

但我找到了另一个解决方案。我编写了一个类来扩展UIAlertController,并在该类中重写了supportedInterfaceOrientationsshouldAutorotate函数。希望这可以帮助您。

class MyUIAlertController : UIAlertController {

       override func supportedInterfaceOrientations() -> UIInterfaceOrientationMask {
              return [UIInterfaceOrientationMask.Portrait,UIInterfaceOrientationMask.PortraitUpsideDown]
       }

       override func shouldAutorotate() -> Bool {
            return false
       }
}

2

我曾经在 iOS 9 的测试版中遇到过这个问题。但显然,苹果在最终发布的 iOS 9 中解决了这个问题。


1
它在9.0.1中没有被修复... :-( - Sendoa
你尝试过在iOS 9.0上吗?这是苹果于9月9日发布的版本。 - Ashvin
是的!我在iOS 9.0.1中发现了一个bug...请看截图 - Sendoa
1
仍然在9.3中发生。 - aclima
1
仍然发生在10中。 - Alexandre G
显示剩余3条评论

0
在我的项目中,我有各种支持不同方向的屏幕,因此一个通用的扩展是不够的。
我的解决方案(Swift 5.2):
import UIKit

class UIAlertControllerWithOrientationSupport : UIAlertController {

    var fixSupportedInterfaceOrientations: UIInterfaceOrientationMask = .allButUpsideDown
    var fixShouldAutorotate: Bool = true

    override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
        return fixSupportedInterfaceOrientations
    }

    override var shouldAutorotate: Bool {
        return fixShouldAutorotate
    }

}

0
这个问题也可以通过在新创建的UIWindow中始终显示警告控制器来解决。请参见此SO答案,了解如何创建一个类别,使您始终以这种方式显示警报。

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