移动父视图时出现约束错误

Posted

技术标签:

【中文标题】移动父视图时出现约束错误【英文标题】:Constraint Error when moving parentView 【发布时间】:2016-06-16 22:46:13 【问题描述】:

我的视图设置具有以下约束:

 bottomContainerViewConstraint = NSLayoutConstraint(item: containerView, attribute: .Bottom, relatedBy: .Equal, toItem: self.view, attribute: .Bottom, multiplier: 1, constant: -10)
    self.view.addConstraint(bottomContainerViewConstraint!)
    topContainerViewConstraint = NSLayoutConstraint(item: containerView, attribute: .Leading, relatedBy: .Equal, toItem: self.view, attribute: .Leading, multiplier: 1, constant: 10)
    self.view.addConstraint(topContainerViewConstraint!)
    self.view.addConstraint(NSLayoutConstraint(item: containerView, attribute: .Trailing, relatedBy: .Equal, toItem: self.view, attribute: .Trailing, multiplier: 1, constant: -10))
    self.view.addConstraint(NSLayoutConstraint(item: containerView, attribute: .Top, relatedBy: .Equal, toItem: self.view, attribute: .Bottom, multiplier: 1, constant: -120))

    //caption and profilepic constraints

    self.view.addConstraint(NSLayoutConstraint(item: captionAndProfileImageContainerView, attribute: .Top, relatedBy: .Equal, toItem: containerView, attribute: .Top, multiplier: 1, constant: 0))
    self.view.addConstraint(NSLayoutConstraint(item: captionAndProfileImageContainerView, attribute: .Leading, relatedBy: .Equal, toItem: containerView, attribute: .Leading, multiplier: 1, constant: 0))
    self.view.addConstraint(NSLayoutConstraint(item: captionAndProfileImageContainerView, attribute: .Trailing, relatedBy: .Equal, toItem: containerView, attribute: .Trailing, multiplier: 1, constant: -110))
    self.view.addConstraint(NSLayoutConstraint(item: captionAndProfileImageContainerView, attribute: .Bottom, relatedBy: .Equal, toItem: containerView, attribute: .Bottom, multiplier: 1, constant: 0))

    self.view.addConstraintsWithFormat("H:|-8-[v0(50)]", views: profilePicImageView)
    self.view.addConstraintsWithFormat("V:|-30-[v0(50)]", views: profilePicImageView)
    profilePicImageView.layer.cornerRadius = 25
    profilePicImageView.layer.masksToBounds = true



    self.view.addConstraint(NSLayoutConstraint(item: captionTextView, attribute: .Top, relatedBy: .Equal, toItem: captionAndProfileImageContainerView, attribute: .Top, multiplier: 1, constant: 0))
    self.view.addConstraint(NSLayoutConstraint(item: captionTextView, attribute: .Leading, relatedBy: .Equal, toItem: profilePicImageView, attribute: .Trailing, multiplier: 1, constant: 8))
    self.view.addConstraint(NSLayoutConstraint(item: captionTextView, attribute: .Trailing, relatedBy: .Equal, toItem: captionAndProfileImageContainerView, attribute: .Trailing, multiplier: 1, constant: 0))
    self.view.addConstraint(NSLayoutConstraint(item: captionTextView, attribute: .Bottom, relatedBy: .Equal, toItem: captionAndProfileImageContainerView, attribute: .Bottom, multiplier: 1, constant: 0))

    //likes and comments and divider


    self.view.addConstraint(NSLayoutConstraint(item: commentAndLikesContainerView, attribute: .Top, relatedBy: .Equal, toItem: containerView, attribute: .Top, multiplier: 1, constant: 0))
    self.view.addConstraint(NSLayoutConstraint(item: commentAndLikesContainerView, attribute: .Leading, relatedBy: .Equal, toItem: captionAndProfileImageContainerView, attribute: .Trailing, multiplier: 1, constant: 0))
    self.view.addConstraint(NSLayoutConstraint(item: commentAndLikesContainerView, attribute: .Trailing, relatedBy: .Equal, toItem: containerView, attribute: .Trailing, multiplier: 1, constant: 0))
    self.view.addConstraint(NSLayoutConstraint(item: commentAndLikesContainerView, attribute: .Bottom, relatedBy: .Equal, toItem: containerView, attribute: .Bottom, multiplier: 1, constant: 0))


    self.view.addConstraint(NSLayoutConstraint(item: voteUpButton, attribute: .Top, relatedBy: .Equal, toItem: commentAndLikesContainerView, attribute: .Top, multiplier: 1, constant: 0))
    self.view.addConstraint(NSLayoutConstraint(item: voteUpButton, attribute: .Leading, relatedBy: .Equal, toItem: commentButton, attribute: .Trailing, multiplier: 1, constant: 0))


    self.view.addConstraint(NSLayoutConstraint(item: likesLabel, attribute: .Top, relatedBy: .Equal, toItem: voteUpButton, attribute: .Bottom, multiplier: 1, constant: -5.5))
    self.view.addConstraint(NSLayoutConstraint(item: likesLabel, attribute: .Leading, relatedBy: .Equal, toItem: voteUpButton, attribute: .Leading, multiplier: 1, constant: 11.5))

    self.view.addConstraint(NSLayoutConstraint(item: voteDownButton, attribute: .Top, relatedBy: .Equal, toItem: likesLabel, attribute: .Bottom, multiplier: 1, constant: 0))
    self.view.addConstraint(NSLayoutConstraint(item: voteDownButton, attribute: .Leading, relatedBy: .Equal, toItem: likesLabel, attribute: .Leading, multiplier: 1, constant: -11.5))

    self.view.addConstraint(NSLayoutConstraint(item: commentButton, attribute: .Top, relatedBy: .Equal, toItem: commentAndLikesContainerView, attribute: .Top, multiplier: 1, constant: 37))
    self.view.addConstraint(NSLayoutConstraint(item: commentButton, attribute: .Leading, relatedBy: .Equal, toItem: commentAndLikesContainerView, attribute: .Leading, multiplier: 1, constant: 10))

    self.view.addConstraint(NSLayoutConstraint(item: commentLabel, attribute: .Top, relatedBy: .Equal, toItem: commentButton, attribute: .Top, multiplier: 1, constant: 7.5))
    self.view.addConstraint(NSLayoutConstraint(item: commentLabel, attribute: .Leading, relatedBy: .Equal, toItem: commentButton, attribute: .Leading, multiplier: 1, constant: 12.5))

现在我正在尝试更改 bottomContainerViewConstrainttopContainerViewConstraint 并使用以下代码将 containerView 位置移动到屏幕顶部:

func moveViewFromBottomToTop(viewToBeMoved : UIView, bottomConstraint : NSLayoutConstraint, topConstraint : NSLayoutConstraint, completionHandler: (loaded: Bool, dataNil: Bool) -> ()) -> () 
    if (topConstraint.constant >  (-self.view.frame.height)) 
        topConstraint.constant = -self.view.frame.height
        bottomConstraint.constant = -self.view.frame.height + 120
        UIView.animateWithDuration(0.5, delay: 0, options: UIViewAnimationOptions.CurveEaseOut, animations: 

            self.view.layoutIfNeeded()

            , completion:  (completed) in


        )
    


代码中提到的所有其他视图都是containerView的子视图。我收到以下错误:

 2016-06-16 23:35:33.282 City[18312:474417] 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:0x7f95e1577e30 UIView:0x7f95e1566670.bottom == UIView:0x7f95e161a710.bottom - 547>",
"<NSLayoutConstraint:0x7f95e159eb40 UIView:0x7f95e1566670.top == UIView:0x7f95e161a710.bottom - 120>",
"<NSLayoutConstraint:0x7f95e15c1160 UIView:0x7f95e15667e0.top == UIView:0x7f95e1566670.top>",
"<NSLayoutConstraint:0x7f95e1502ed0 UIView:0x7f95e15667e0.bottom == UIView:0x7f95e1566670.bottom>",
"<NSLayoutConstraint:0x7f95e15163b0 UITextView:0x7f95e2107c00.top == UIView:0x7f95e15667e0.top>",
"<NSLayoutConstraint:0x7f95e1552b50 UITextView:0x7f95e2107c00.bottom == UIView:0x7f95e15667e0.bottom>"
)

Will attempt to recover by breaking constraint 
 <NSLayoutConstraint:0x7f95e159eb40 UIView:0x7f95e1566670.top == UIView:0x7f95e161a710.bottom - 120>

我不明白为什么这是个问题。这些约束不应该只是自动调整,因为它们都是 containerView 的子视图,并且所有约束都是相对于 containerView 的吗?

【问题讨论】:

【参考方案1】:

不要忘记如果你使用代码约束,你需要禁用 translateAutoResizingMaskIntoConstraints

例如:

captionAndProfileImageContainerView.translateAutoresizingMaskIntoConstraints = false
captionTextView.translateAutoresizingMaskIntoConstraints = false

对所有子视图都这样做

【讨论】:

以上是关于移动父视图时出现约束错误的主要内容,如果未能解决你的问题,请参考以下文章

在 IOS 中移动到视图控制器时出现问题

滑动 UIView 时出现动画错误

插入失败时出现约束错误

iOS 8 键盘扩展:出现呼叫栏时出现约束错误?

在更新触发之前执行时出现约束冲突错误

从 CSV 填充 postgres 表列时出现非空约束错误