2015-05-15 70 views
-1

這是我的UIViewController之前,我按下一個按鈕(我沒有把它放在那裏,因爲它是不相關):我的自動佈局約束有什麼問題?

enter image description here

當我按下按鈕,包含兩個UIPickerView一個UIView從頂部出現。在這個UIView下有2個UIButtons。寄託都帶有自動佈局工作:

enter image description here

下面是代碼,當我創建約束:

let okButtonHeight: CGFloat = 53 
let okButtonWidth: CGFloat = 53 
let leftPickerViewWidth: CGFloat = 80 
let leftPickerViewHeight: CGFloat = 200 
let margin: CGFloat = 8 

// frame 
let constraint0 = NSLayoutConstraint(item: okButton, attribute: .Bottom, relatedBy: .Equal, toItem: self.view, attribute: .Top, multiplier: 1, constant: 0) 
let constraint1 = NSLayoutConstraint(item: frameView, attribute: .CenterX, relatedBy: .Equal, toItem: view, attribute: .CenterX, multiplier: 1, constant: 0) 

// left & right pickerViews 
let constraint2 = NSLayoutConstraint(item: leftPickerView, attribute: .Width, relatedBy: .Equal, toItem: rightPickerView, attribute: .Width, multiplier: 1, constant: 0) 
let constraint3 = NSLayoutConstraint(item: leftPickerView, attribute: .Height, relatedBy: .Equal, toItem: rightPickerView, attribute: .Height, multiplier: 1, constant: 0) 
let constraint4 = NSLayoutConstraint(item: leftPickerView, attribute: .Trailing, relatedBy: .Equal, toItem: rightPickerView, attribute: .Leading, multiplier: 1, constant: -margin) 
let constraint5 = NSLayoutConstraint(item: leftPickerView, attribute: .Top, relatedBy: .Equal, toItem: rightPickerView, attribute: .Top, multiplier: 1, constant: 0) 

// left pickerView 
let constraint6 = NSLayoutConstraint(item: leftPickerView, attribute: .Height, relatedBy: .Equal, toItem: nil, attribute: .NotAnAttribute, multiplier: 1, constant: leftPickerViewHeight) 
let constraint7 = NSLayoutConstraint(item: leftPickerView, attribute: .Width, relatedBy: .Equal, toItem: nil, attribute: .NotAnAttribute, multiplier: 1, constant: leftPickerViewWidth) 
let constraint8 = NSLayoutConstraint(item: leftPickerView, attribute: .Top, relatedBy: .Equal, toItem: frameView, attribute: .Top, multiplier: 1, constant: -margin) 
let constraint9 = NSLayoutConstraint(item: leftPickerView, attribute: .Bottom, relatedBy: .Equal, toItem: frameView, attribute: .Bottom, multiplier: 1, constant: margin) 
let constraint10 = NSLayoutConstraint(item: leftPickerView, attribute: .Leading, relatedBy: .Equal, toItem: frameView, attribute: .Leading, multiplier: 1, constant: margin) 

// right pickerView 
let constraint11 = NSLayoutConstraint(item: rightPickerView, attribute: .Trailing, relatedBy: .Equal, toItem: frameView, attribute: .Trailing, multiplier: 1, constant: -margin) 

// ok & cancel buttons 
let constraint12 = NSLayoutConstraint(item: okButton, attribute: .Top, relatedBy: .Equal, toItem: cancelButton, attribute: .Top, multiplier: 1, constant: 0) 
let constraint13 = NSLayoutConstraint(item: okButton, attribute: .Bottom, relatedBy: .Equal, toItem: cancelButton, attribute: .Bottom, multiplier: 1, constant: 0) 
let constraint14 = NSLayoutConstraint(item: okButton, attribute: .Width, relatedBy: .Equal, toItem: cancelButton, attribute: .Width, multiplier: 1, constant: 0) 
let constraint15 = NSLayoutConstraint(item: okButton, attribute: .Height, relatedBy: .Equal, toItem: cancelButton, attribute: .Height, multiplier: 1, constant: 0) 

// ok button 
let constraint16 = NSLayoutConstraint(item: view, attribute: .CenterX, relatedBy: .Equal, toItem: okButton, attribute: .Trailing, multiplier: 1, constant: 10) 
let constraint17 = NSLayoutConstraint(item: okButton, attribute: .Width, relatedBy: .Equal, toItem: nil, attribute: .NotAnAttribute, multiplier: 1, constant: okButtonWidth) 
let constraint18 = NSLayoutConstraint(item: okButton, attribute: .Height, relatedBy: .Equal, toItem: nil, attribute: .NotAnAttribute, multiplier: 1, constant: okButtonHeight) 
let constraint19 = NSLayoutConstraint(item: okButton, attribute: .Top, relatedBy: .Equal, toItem: frameView, attribute: .Bottom, multiplier: 1, constant: 10) 

// cancel button 
let constraint20 = NSLayoutConstraint(item: view, attribute: .CenterX, relatedBy: .Equal, toItem: cancelButton, attribute: .Leading, multiplier: 1, constant: -10) 

view.addConstraint(constraint0) 
view.addConstraint(constraint1) 
view.addConstraint(constraint12) 
view.addConstraint(constraint13) 
view.addConstraint(constraint14) 
view.addConstraint(constraint15) 
view.addConstraint(constraint16) 
view.addConstraint(constraint17) 
view.addConstraint(constraint18) 
view.addConstraint(constraint19) 
view.addConstraint(constraint20) 

frameView.addConstraint(constraint2) 
frameView.addConstraint(constraint3) 
frameView.addConstraint(constraint4) 
frameView.addConstraint(constraint5) 
frameView.addConstraint(constraint6) 
frameView.addConstraint(constraint7) 
frameView.addConstraint(constraint8) 
frameView.addConstraint(constraint9) 
frameView.addConstraint(constraint10) 
frameView.addConstraint(constraint11) 

selectionCurrencyConstraintList = [constraint0, constraint1, constraint2, constraint3, constraint4, constraint5, constraint6, constraint7, constraint8, constraint9, constraint10, constraint11, constraint12, constraint13, constraint14, constraint15, constraint16, constraint17, constraint18, constraint19, constraint20] 

frameView.hidden = true 
okButton.hidden = true 
cancelButton.hidden = true 

在這一點上,UIView的和兩個按鈕都隱藏正上方的頂部屏幕。當我通過這一個NSLayoutConstraint(item: frameView, attribute: .Top, relatedBy: .Equal, toItem: topView, attribute: .Bottom, multiplier: 1, constant: margin)它工作正常替換該約束NSLayoutConstraint(item: okButton, attribute: .Bottom, relatedBy: .Equal, toItem: self.view, attribute: .Top, multiplier: 1, constant: 0)

frameView.hidden = hide 
okButton.hidden = hide 
cancelButton.hidden = hide 

if var constraints = selectionCurrencyConstraintList { 
    let topFrameConstraint = constraints[0] 
    view.removeConstraint(topFrameConstraint) 
    constraints.removeAtIndex(0) 
    let newTopConstraint: NSLayoutConstraint! 
    if hide { 
     newTopConstraint = NSLayoutConstraint(item: okButton, attribute: .Bottom, relatedBy: .Equal, toItem: self.view, attribute: .Top, multiplier: 1, constant: 0) 
    } else { 
     newTopConstraint = NSLayoutConstraint(item: frameView, attribute: .Top, relatedBy: .Equal, toItem: topView, attribute: .Bottom, multiplier: 1, constant: margin) 
    } 
    constraints.insert(newTopConstraint, atIndex: 0) 
    view.addConstraint(newTopConstraint) 
} 

UIView.animateWithDuration(0.5) { 
    self.view.layoutIfNeeded() 
} 

當我按下按鈕,使它看起來,我執行該代碼。

當我扭轉它,我得到了一些約束不能滿足:

2015-05-15 20:17:25.374 CurrencyEx[624:42779] 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) 
(
    "<NSLayoutConstraint:0x17408de30 V:[UIView:0x174186660(50)]>", 
    "<NSLayoutConstraint:0x174090fe0 V:[_UILayoutGuide:0x1741a8a40]-(0)-[UIView:0x174186660]>", 
    "<_UILayoutSupportConstraint:0x1740a3e40 V:[_UILayoutGuide:0x1741a8a40(20)]>", 
    "<_UILayoutSupportConstraint:0x1740a3d80 V:|-(0)-[_UILayoutGuide:0x1741a8a40] (Names: '|':UIView:0x174186590)>", 
    "<NSLayoutConstraint:0x170089150 V:[UIButton:0x146e49020(53)]>", 
    "<NSLayoutConstraint:0x1700891a0 V:[UIView:0x1741868d0]-(10)-[UIButton:0x146e49020]>", 
    "<NSLayoutConstraint:0x170088d90 V:[UIPickerView:0x146e09ef0(200)]>", 
    "<NSLayoutConstraint:0x170088e30 V:|-(-8)-[UIPickerView:0x146e09ef0] (Names: '|':UIView:0x1741868d0)>", 
    "<NSLayoutConstraint:0x170088e80 UIPickerView:0x146e09ef0.bottom == UIView:0x1741868d0.bottom + 8>", 
    "<NSLayoutConstraint:0x17008ef60 V:[UIView:0x174186660]-(8)-[UIView:0x1741868d0]>", 
    "<NSLayoutConstraint:0x174096620 UIButton:0x146e49020.bottom == UIView:0x174186590.top>" 
) 

Will attempt to recover by breaking constraint 
<NSLayoutConstraint:0x170088e80 UIPickerView:0x146e09ef0.bottom == UIView:0x1741868d0.bottom + 8> 

Make a symbolic breakpoint at UIViewAlertForUnsatisfiableConstraints to catch this in the debugger. 
The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKit/UIView.h> may also be helpful. 
2015-05-15 20:17:25.377 CurrencyEx[624:42779] 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) 
(
    "<NSLayoutConstraint:0x17408de30 V:[UIView:0x174186660(50)]>", 
    "<NSLayoutConstraint:0x174090fe0 V:[_UILayoutGuide:0x1741a8a40]-(0)-[UIView:0x174186660]>", 
    "<_UILayoutSupportConstraint:0x1740a3e40 V:[_UILayoutGuide:0x1741a8a40(20)]>", 
    "<_UILayoutSupportConstraint:0x1740a3d80 V:|-(0)-[_UILayoutGuide:0x1741a8a40] (Names: '|':UIView:0x174186590)>", 
    "<NSLayoutConstraint:0x170089150 V:[UIButton:0x146e49020(53)]>", 
    "<NSLayoutConstraint:0x1700891a0 V:[UIView:0x1741868d0]-(10)-[UIButton:0x146e49020]>", 
    "<NSLayoutConstraint:0x17008ef60 V:[UIView:0x174186660]-(8)-[UIView:0x1741868d0]>", 
    "<NSLayoutConstraint:0x174096620 UIButton:0x146e49020.bottom == UIView:0x174186590.top>" 
) 

Will attempt to recover by breaking constraint 
<NSLayoutConstraint:0x17408de30 V:[UIView:0x174186660(50)]> 

Make a symbolic breakpoint at UIViewAlertForUnsatisfiableConstraints to catch this in the debugger. 
The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKit/UIView.h> may also be helpful. 
2015-05-15 20:17:25.378 CurrencyEx[624:42779] 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) 
(
    "<NSLayoutConstraint:0x174090fe0 V:[_UILayoutGuide:0x1741a8a40]-(0)-[UIView:0x174186660]>", 
    "<_UILayoutSupportConstraint:0x1740a3e40 V:[_UILayoutGuide:0x1741a8a40(20)]>", 
    "<_UILayoutSupportConstraint:0x1740a3d80 V:|-(0)-[_UILayoutGuide:0x1741a8a40] (Names: '|':UIView:0x174186590)>", 
    "<NSLayoutConstraint:0x170089150 V:[UIButton:0x146e49020(53)]>", 
    "<NSLayoutConstraint:0x1700891a0 V:[UIView:0x1741868d0]-(10)-[UIButton:0x146e49020]>", 
    "<NSLayoutConstraint:0x17008ef60 V:[UIView:0x174186660]-(8)-[UIView:0x1741868d0]>", 
    "<NSLayoutConstraint:0x174096620 UIButton:0x146e49020.bottom == UIView:0x174186590.top>" 
) 

Will attempt to recover by breaking constraint 
<NSLayoutConstraint:0x1700891a0 V:[UIView:0x1741868d0]-(10)-[UIButton:0x146e49020]> 

我不明白爲什麼。它首先適用於這些限制。當我修改它們中的一些時,它可以工作,並且當我將它們放回去時,它不再起作用...

任何想法?

+0

嘗試在故事板中設置所有約束,然後在每個動畫設置setTranslatesAutoresizingMaskIntoConstraints(_ :)'爲YES之前爲什麼 –

+0

爲什麼要將它設置爲YES?它不適用於自動佈局,然後 – Nico

+0

您不需要重置所有約束的常量。 –

回答

3

讓我們打電話給你的約束:

ConstraintHideokButton底部與上海華頂部對齊。
ConstraintShowframeView是在topView下8分。

如果您逐個檢查日誌中的碰撞限制,您會發現同時存在兩個約束條件ConstraintHideConstraintShow

這是由於您刪除/添加約束引起的。

  1. 初始狀態

只有ConstraintHide是在視圖

表示

ConstraintHide正確刪除視圖後

  • 狀態,ConstraintShow加入

    1. 狀態隱藏視圖
    2. 不除去

    ConstraintShow後,加入ConstraintHide

    1. 碰撞

    現在的問題是爲什麼步驟3沒有除去約束?這是因爲一個錯誤的步驟2.您selectionCurrencyConstraintList沒有正確更新,所以在第3步你正在試圖刪除原來的ConstraintHide約束,而不是一步添加的約束ConstraintShow 2.

    這是由於這樣的事實: if var constraints = selectionCurrencyConstraintList製作數組的副本。所以你必須最後保存更改。

    添加

    selectionCurrencyConstraintList = constraints

    到塊的末尾。

    說了這麼多,你可以顯着通過將所有在Interface Builder中的約束簡化代碼,連接ConstraintShowConstraintHide爲網點和,而不是刪除/ addding他們,只是他們0更改優先級,以1000

  • +0

    我的英雄!是的,我意識到如果是可選綁定,當你說我實際上可能不會刪除我以爲我刪除了的東西。非常感謝! – Nico

    +0

    順便說一句,你如何設法在這個日誌中看到我的約束'ConstraintHide'和'ConstraintShow'?沒有更簡單的方法來顯示約束的實際名稱,而不僅僅是一些十六進制代碼? – Nico

    +1

    @Nico我只是將日誌1中的約束條件與1進行比較,並且意識到什麼是指針意味着什麼,但是如果您在調試器中進行操作,則可以使用'po 0x1741a8a40'打印出對象。或者你可以打印出整個視圖層次結構,然後比較這些指針。 – Sulthan