从 MSMessagesAppViewController 正确显示 UIAlertController

Posted

技术标签:

【中文标题】从 MSMessagesAppViewController 正确显示 UIAlertController【英文标题】:Properly Present a UIAlertController from MSMessagesAppViewController 【发布时间】:2016-09-29 01:15:48 【问题描述】:

我正在尝试弄清楚如何在我的 iMessage 应用程序扩展中显示具有 UIAlertControllerStyleActionSheet 样式的 UIAlertController

问题是,当调用时,操作表出现在原生 iMessage 文本字段下方:

[self.view.window.rootViewController presentViewController:actionSheetController animated:YES completion:NULL];

我将如何解决这个问题?

代码:

UIAlertController *actionSheetController = [UIAlertController alertControllerWithTitle:NSLocalizedString(@"Clear", nil) message:nil preferredStyle:UIAlertControllerStyleActionSheet];

UIAlertAction *clear = [UIAlertAction actionWithTitle:NSLocalizedString(@"Clear", nil) style:UIAlertActionStyleDestructive handler:^(UIAlertAction *action)

    [self clear];
];

UIAlertAction *cancel = [UIAlertAction actionWithTitle:NSLocalizedString(@"Cancel", nil) style:UIAlertActionStyleCancel handler:^(UIAlertAction *action)
];

[actionSheetController addAction:clear];
[actionSheetController addAction:cancel];

[self.view.window.rootViewController presentViewController:actionSheetController animated:YES completion:NULL];

【问题讨论】:

你能在MSMessagesAppViewController上介绍UIAlertController吗? 这是一个已知问题。来自 ios 10/10.1 发行说明:“当 UIAlertController 对象出现在 Messages 扩展中时,它会被扩展的底栏截断。”打开错误报告告诉 Apple 这对您很重要。 iMessage 文本字段属于高于您的self.view.window 但低于状态栏的某个窗口。可能您可能想尝试使用windowLevel = UIWindowLevelStatusBar 添加新的UIWindow 并从该窗口显示警报 @VladFedoseev 刚刚尝试过,但没有成功。 UIWindow *window = UIWindow.new; window.rootViewController = self; window.windowLevel = UIWindowLevelStatusBar; [window makeKeyAndVisible]; [window.rootViewController presentViewController:alertController animated:YES completion:NULL]; 我可以毫无问题地展示带有 AlertStyle 的 UIAlertController。但是,我在解雇时偶尔会崩溃,所以我建议创建一个 UIView 并将其作为子视图添加到 MSMessagesAppViewController 【参考方案1】:

这是一种解决方法。可以加一点动画让它流畅。

[self.view.window.rootViewController presentViewController:actionSheetController animated:YES completion:^
    actionSheetController.view.frame = CGRectOffset(actionSheetController.view.frame, 0, -40);
];

【讨论】:

这是有问题的,因为任何布局传递都会将警报控制器的视图移动到其原始位置。 @LeoNatan,如果需要,您可以 KVO 中心属性并重新调整框架【参考方案2】:

另一种解决方法:

actionSheetController.view.transform = CGAffineTransform(translationX: 0, y: -40)    
[self.view.window.rootViewController presentViewController:actionSheetController animated:YES completion:NULL];

【讨论】:

你也可以用UIAlertControllerStyleAlert作为你的UIAlertController preferredStyle:...警报总是出现在屏幕中间(即使在ipad上)...最后我自己用了...跨度> 【参考方案3】:

不要硬编码操作表的 y 位置。

当苹果更改 iMessage 扩展坞的高度时,这可能会导致以后的 iOS 主要更新出现 ui 问题。而是使用safeAreaInsets.bottom 值来找出视图被停靠栏隐藏的值。

这是我们正在使用的解决方案:

    let actionSheet = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet)

    actionSheet.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler:  (_) in
        actionSheet.dismiss(animated: true, completion: nil)
    ))

    // Adding further actions...

    present(actionSheet, animated: true) 
        UIView.animate(withDuration: 0.2, animations: 
            actionSheet.view.frame = CGRect(x: actionSheet.view.frame.minX,
                                            y: actionSheet.view.frame.minY - self.view.safeAreaInsets.bottom,
                                            width: actionSheet.view.frame.width,
                                            height: actionSheet.view.frame.height)
        )
    

详细信息:操作表被 iMessage 停靠栏隐藏,因为您在其上显示操作表的视图控制器视图被绑定到视图底部而不是顶部iMessage 底座。必须考虑这种情况,例如向其他视图及其子视图添加约束时。


更新:

只需使用以下代码即可避免上述动画。就我而言,在看到动画之后确实变得很烦人。

extension UIAlertController 
    open override func viewDidLayoutSubviews() 
        super.viewDidLayoutSubviews()
        guard let viewController = presentingViewController else  return 
        view.transform = .identity
        view.transform = .init(translationX: 0.0, y: - viewController.view.safeAreaInsets.bottom)
    

【讨论】:

【参考方案4】:

根据this,您可以通过以下方式请求全屏演示:

[self requestPresentationStyle:MSMessagesAppPresentationStyleExpanded];

在您的代码之前:

[self.view.window.rootViewController presentViewController:actionSheetController animated:YES completion:NULL];

【讨论】:

没有帮助。即使展开后,警报控制器仍会出现在输入栏下方。

以上是关于从 MSMessagesAppViewController 正确显示 UIAlertController的主要内容,如果未能解决你的问题,请参考以下文章

从PRISM开始学WPFMVVMViewModel?

在 python 中,为啥从数组读取比从列表读取慢?

从图库中挑选或从相机捕获的高质量图像

从PRISM开始学WPFMVVMCommand?

从PRISM开始学WPFPrism?

mysql 主-主-从-从