Swift默认AlertViewController突破约束

lin*_*ram 37 iphone xcode ios swift ios-autolayout

我正在尝试使用样式为.actionSheet的默认AlertViewController。由于某种原因,警报导致约束错误。只要没有通过按钮触发(显示)alertController,整个视图就不会出现约束错误。难道这是Xcode错误?

我得到的确切错误如下所示:

2019-04-12 15:33:29.584076+0200 Appname[4688:39368] [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. 
(
    "<NSLayoutConstraint:0x6000025a1e50 UIView:0x7f88fcf6ce60.width == - 16   (active)>"
)

Will attempt to recover by breaking constraint 
<NSLayoutConstraint:0x6000025a1e50 UIView:0x7f88fcf6ce60.width == - 16   (active)>

Run Code Online (Sandbox Code Playgroud)

这是我使用的代码:

@objc func changeProfileImageTapped(){
        print("ChangeProfileImageButton tapped!")
        let alert = UIAlertController(title: "Change your profile image", message: nil, preferredStyle: .actionSheet)

        alert.addAction(UIAlertAction(title: "Photo Library", style: .default, handler: nil))
        alert.addAction(UIAlertAction(title: "Online Stock Library", style: .default, handler: nil))
        alert.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: nil))
        alert.view.tintColor = ColorCodes.logoPrimaryColor

        self.present(alert, animated: true)
    }
Run Code Online (Sandbox Code Playgroud)

如您所见,这是非常基本的。这就是为什么我对我得到的奇怪行为感到非常困惑,因为此默认实现不应导致任何错误,对吗?

输出我得到

尽管通过打破限制,警报可以在所有屏幕尺寸上正常显示,但我非常感谢我所获得的任何帮助。

Agi*_*ght 30

此错误并不严重,似乎是Apple修复的错误。出现后,此约束以动画样式显示。在此处输入图片说明 在展示之前,我尝试捕获并更改它(更改值,关系,优先级)–由于这种动态添加的约束,因此没有成功。

当您关闭动画self.present(alert, animated: false)并使用alert.view.addSubview(UIView())–错误消失。我无法解释,但可以!

let alert = UIAlertController(title: "Change your profile image", message: nil, preferredStyle: .actionSheet)

alert.addAction(UIAlertAction(title: "Photo Library", style: .default, handler: nil))
alert.addAction(UIAlertAction(title: "Online Stock Library", style: .default, handler: nil))
let cancel = UIAlertAction(title: "Cancel", style: .destructive, handler: nil)

alert.addAction(cancel)
alert.view.addSubview(UIView()) // I can't explain it, but it works!

self.present(alert, animated: false)
Run Code Online (Sandbox Code Playgroud)

  • 关闭对我有用的动画+`alert.view.addSubview(UIView())`。但是没有动画,感觉就很奇怪...无论如何,谢谢您的解决方案。 (2认同)
  • 当“动画”设置为true时,会发生此问题。我认为这是一个内部错误,由于actoinSheet正确显示,因此可以忽略。我很高兴可以将其范围缩小到根本原因,起初我教过它是我的代码。 (2认同)

And*_*nov 20

这是 iOS 版本中的一个新错误:

  • 12.2
  • 12.3
  • 12.4
  • 13.0
  • 13.1
  • 13.2
  • 13.2.3
  • 13.3
  • 13.4
  • 13.4.1
  • 13.5
  • 13.6
  • 14.0
  • 14.2
  • 14.4

我们唯一能做的就是向 Apple 提交错误报告(我刚刚这样做了,你也应该这样做)。

当新版本的 iOS 出现时,我会尝试更新它的答案。

  • 看起来他们在 iOS 14.5 中修复了它 - 使用 iPhone SE2 模拟器在 Swift 5/Xcode 12.5/iOS 12.3 项目中进行了测试。在同一个项目中,iPhone SE 12.4 模拟器将消息记录在控制台中。 (2认同)

小智 8

添加到这个答案......这似乎为我解决了这个问题,并且不需要对现有代码进行任何更改。

extension UIAlertController {
    override open func viewDidLoad() {
        super.viewDidLoad()
        pruneNegativeWidthConstraints()
    }

    func pruneNegativeWidthConstraints() {
        for subView in self.view.subviews {
            for constraint in subView.constraints where constraint.debugDescription.contains("width == - 16") {
                subView.removeConstraint(constraint)
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)


小智 5

以下内容删除了警告,而无需禁用动画。并且假设苹果最终解决了警告的根本原因,那么它就不会破坏其他任何东西。

extension UIAlertController {
    func pruneNegativeWidthConstraints() {
        for subView in self.view.subviews {
            for constraint in subView.constraints where constraint.debugDescription.contains("width == - 16") {
                subView.removeConstraint(constraint)
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

然后可以这样使用:

alertController.pruneNegativeWidthConstraints()
Run Code Online (Sandbox Code Playgroud)