iPhone 上显示的 UIAlertController,iPad 上未显示

UIAlertController shown on iPhone, not on iPad

我在视图控制器上呈现 UIAlertController 操作 sheet。这在 iPhone 上运行良好。在 iPad 上我什么也没看到,但控制台警告我布局约束似乎将其高度设置为 0:

2022-02-22 22:00:26.032174+0100 Sandbox[15099:651165] [LayoutConstraints] Unable to simultaneously satisfy constraints.
    Probably at least one of the constraints in the following list is one you don't want. 
    Try this: 
        (1) look at each constraint and try to figure out which you don't expect; 
        (2) find the code that added the unwanted constraint or constraints and fix it. 
    (Note: If you're seeing NSAutoresizingMaskLayoutConstraints that you don't understand, refer to the documentation for the UIView property translatesAutoresizingMaskIntoConstraints) 
(
    "<NSAutoresizingMaskLayoutConstraint:0x6000024aecb0 h=--& v=--& UIView:0x155609dd0.width == 0   (active)>",
    "<NSLayoutConstraint:0x6000024ad0e0 UIView:0x15550be40.width == 304   (active)>",
    "<NSLayoutConstraint:0x6000024926c0 _UIAlertControllerView:0x15550b850.width >= UIView:0x15550be40.width   (active)>",
    "<NSLayoutConstraint:0x6000024ae260 UIView:0x155609dd0.width == _UIAlertControllerView:0x15550b850.width   (active)>"
)

Will attempt to recover by breaking constraint 
<NSLayoutConstraint:0x6000024ad0e0 UIView:0x15550be40.width == 304   (active)>

Make a symbolic breakpoint at UIViewAlertForUnsatisfiableConstraints to catch this in the debugger.
The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKitCore/UIView.h> may also be helpful.
2022-02-22 22:00:26.032639+0100 Sandbox[15099:651165] [LayoutConstraints] Unable to simultaneously satisfy constraints.
    Probably at least one of the constraints in the following list is one you don't want. 
    Try this: 
        (1) look at each constraint and try to figure out which you don't expect; 
        (2) find the code that added the unwanted constraint or constraints and fix it. 
    (Note: If you're seeing NSAutoresizingMaskLayoutConstraints that you don't understand, refer to the documentation for the UIView property translatesAutoresizingMaskIntoConstraints) 
(
    "<NSAutoresizingMaskLayoutConstraint:0x6000024aed50 h=--& v=--& UIView:0x155609dd0.height == 13   (active)>",
    "<NSLayoutConstraint:0x600002492710 _UIAlertControllerView:0x15550b850.height == UIView:0x15550be40.height   (active)>",
    "<NSLayoutConstraint:0x6000024adc70 UIView:0x155609dd0.height == _UIAlertControllerView:0x15550b850.height   (active)>",
    "<NSLayoutConstraint:0x600002491f90 UIView:0x15550be40.height >= 44   (active)>"
)

Will attempt to recover by breaking constraint 
<NSLayoutConstraint:0x600002491f90 UIView:0x15550be40.height >= 44   (active)>

Make a symbolic breakpoint at UIViewAlertForUnsatisfiableConstraints to catch this in the debugger.
The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKitCore/UIView.h> may also be helpful.

要重现这一点,您可以在 Xcode 中创建一个新应用程序(我使用的是 Storyboard 选项,Objective-C)并将 ViewController.m 代码更改为

#import "ViewController.h"

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    [self.view addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(gestureRecognized:)]];
}

- (void)gestureRecognized:(id)sender {
    UIAlertController *alertController = [UIAlertController alertControllerWithTitle:nil message:nil preferredStyle:UIAlertControllerStyleActionSheet];
    [alertController addAction:[UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleDefault handler:NULL]];
    alertController.popoverPresentationController.sourceView = self.view;
    [self presentViewController:alertController animated:YES completion:NULL];
}

@end

以防万一,我使用 Xcode 13.2.1 和 iOS 15.2 模拟器(iPhone SE - 第 2 代和 iPad 第 9 代)但是拥有真实设备的用户也可以复制它。

如果您查看 sourceView 属性 (https://developer.apple.com/documentation/uikit/uipopoverpresentationcontroller/1622313-sourceview) 的文档,您会发现它被定义为“包含弹出框锚点矩形的视图”。

这意味着您的弹出窗口出现在屏幕外,因为锚点矩形就是视图本身。

要解决此问题,请尝试同时修改 sourceRect 属性。这是一个例子:

alertController.popoverPresentationController.sourceRect = CGRectMake(CGRectGetMidX(self.view.bounds), CGRectGetMidY(self.view.bounds), 1, 1);

您会看到这会导致警报出现在视图中间。