Swift中如何修复UIAlertController的ActionSheet约束冲突问题
解决iOS 12.2 + Xcode 10.2下UIAlertActionSheet约束冲突问题
我之前升级到相同的系统版本组合后,也遇到了一模一样的约束冲突警告——界面运行完全正常,但弹出ActionSheet时Xcode控制台会抛出一堆约束错误,重置界面约束根本没用,因为问题出在系统UIAlertController的内部布局逻辑上。
针对你的代码,这里有几个经过验证的解决方案,按推荐程度排序:
方案一:正确设置PopoverPresentationController的源(最推荐)
虽然在iPhone上ActionSheet是全屏弹出,但iOS 12.2之后系统内部对ActionSheet的布局计算依赖于popoverPresentationController的源信息。你可以在present之前给alertController指定触发它的UIBarButtonItem:
修改你的代码,在self.present(alertController,animated: true,completion: nil)之前添加一行关键代码:
// 给ActionSheet指定触发源,解决布局约束歧义 alertController.popoverPresentationController?.barButtonItem = sender
完整修改后的代码片段:
@IBAction func newToDoBarButtonTapped(_ sender: UIBarButtonItem) { let alertController = UIAlertController(title: "New or Edit", message: nil, preferredStyle: .actionSheet) let newToDoAlertAction = UIAlertAction(title: "New Item", style: .default, handler: {(_) in let mainStoryboard = UIStoryboard(name: "Main", bundle: nil) let registerVC = mainStoryboard.instantiateViewController(withIdentifier: "NewToDoStoryboard") as! ToDoViewController self.navigationController?.pushViewController(registerVC, animated: true) }) let editInformationOfListAction = UIAlertAction(title: "Edit Information", style: .default, handler: {(_) in let mainStoryboard = UIStoryboard(name: "Main", bundle: nil) let registerVC = mainStoryboard.instantiateViewController(withIdentifier: "EditStoryboard") as! EditItemTableViewController self.navigationController?.pushViewController(registerVC, animated: true) }) let cancelAction = UIAlertAction(title: "Cancel", style: .cancel, handler: nil) alertController.addAction(newToDoAlertAction) alertController.addAction(editInformationOfListAction) alertController.addAction(cancelAction) // 添加这行代码解决约束冲突 alertController.popoverPresentationController?.barButtonItem = sender self.present(alertController,animated: true,completion: nil) }
这个方法让系统明确知道ActionSheet的触发位置,从而正确计算内部布局,彻底消除约束冲突警告,同时还能兼容iPad上的popover展示逻辑。
方案二:手动设置PreferredContentSize
如果方案一无效,你可以尝试强制指定ActionSheet的宽度,让系统按固定宽度布局:
在present之前添加:
alertController.preferredContentSize = CGSize(width: self.view.bounds.width, height: alertController.preferredContentSize.height)
这个方法通过固定宽度避免系统在计算布局时出现约束歧义,虽然不如方案一优雅,但也能解决问题。
补充说明
这个约束冲突是iOS 12.2和Xcode 10.2的一个已知系统级问题,苹果在后续的iOS版本中已经修复了,但如果需要兼容iOS 12.2,上面的方案可以有效消除警告。
内容的提问来源于stack exchange,提问作者Huang Runhua
相关产品推荐
相关产品推荐

