2014年5月1日

How to resolve "Unable to simultaneously satisfy constraints" error in ios

在 IPhone 4S 以前,螢幕大小是等比放大的,但 IPhone 5/5S 就不是等比放大了。因此工程師們在設計 app 時,為了讓畫面在所有 device 都不跑版,就可能用 code 的方式產生畫面中所有元件,另一種方式就是使用 storyboard 搭配 auto layout,而 constraints 就是 storyboard 搭配 auto layout 時會使用到的一種技術

constraints

  • 在 storyboard 中使用 auto layout 才會出現
  • 元件對齊的條件,包含元件與父容器、元件寬高、元件間對齊等等
  • 可在 storyboard 中設定,也可用 code 設定

Unable to simultaneously satisfy constraints problem

  • 在 storyboard 中設定 constraints 後,為了畫面的顯示,又再 controller 中動態修改,導致部分 constraints 發生衝突
  • 錯誤訊息

2014-04-09 16:03:23.280 kokola[4077:60b] 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:0x8d8f340 H:[UILabel:0x100e120(165)]>",
    "<NSLayoutConstraint:0x8d74d20 H:[UILabel:0x1006630(0)]>",
    "<NSLayoutConstraint:0x100a1c0 H:[UIView:0x101c6a0(190)]>",
    "<NSLayoutConstraint:0x8d81620 H:|-(0)-[UILabel:0x100e120]   (Names: '|':UIView:0x101c6a0 )>",
    "<NSLayoutConstraint:0x100e860 H:[UILabel:0x1006630]-(0)-|   (Names: '|':UIView:0x101c6a0 )>",
    "<NSLayoutConstraint:0x10085b0 H:[UILabel:0x100e120]-(0)-[UILabel:0x1006630]>"
)

Will attempt to recover by breaking constraint 


Break on objc_exception_throw to catch this in the debugger.
The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in  may also be helpful.

2014-04-14 09:58:01.131 kokola[3511:60b] 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:0x8f604d0 V:[UIView:0x8f63e40(88)]>",
    "<NSLayoutConstraint:0x1016af0 V:[UIView:0x8f560a0(0)]>",
    "<NSLayoutConstraint:0x1016b20 V:|-(0)-[UIView:0x8f63e40]   (Names: '|':UIView:0x8f560a0 )>",
    "<NSLayoutConstraint:0x1016be0 V:[UIView:0x8f63e40]-(0)-|   (Names: '|':UIView:0x8f560a0 )>"
)

Will attempt to recover by breaking constraint 

solve

  1. 看懂錯誤訊息
    (1) 方向與 constraint value
    
    "<NSLayoutConstraint:0x8d8f340 H:[UILabel:0x100e120(165)]>"
    
    在上方錯誤訊息中," H " 代表 Horizontal,而 165 代表 constraint value,UILabel 當然就是元件啦!
    由以上訊息可以知道,在 storyboard 中有某個寬度為 165 的 UILabel
  2. 
    "<NSLayoutConstraint:0x8f604d0 V:[UIView:0x8f63e40(88)]>"
    
    看完前一個錯誤訊息後,應該不難猜到上面錯誤訊息中的 " V " 就是 Vertical,所以由這個錯誤訊息可以知道,在 storyboard 中有某個高度為 88 的 UIView

    (2) constraint 對齊
    
    "<NSLayoutConstraint:0x8d81620 H:|-(0)-[UILabel:0x100e120]   (Names: '|':UIView:0x101c6a0 )>"
    
    從前面的錯誤訊息得知 " H " 代表 Horizontal,而 " H: " 後面的 " |-(0)- " 代表對齊方式與 constraint value。其中 " | " 代表對齊的方向;" - " 代表間距;" () " 中的數值代表 constraint value,而後面的 UIView 則代表與 UILabel 對齊的元件。所以上面的錯誤訊息表示,在 storyboard 中有一個 UILabel 與左邊 UIView 間距是 0
    
    "<NSLayoutConstraint:0x1016b20 V:|-(0)-[UIView:0x8f63e40]   (Names: '|':UIView:0x8f560a0 )>"
    
    前面的解說判斷,上面的錯誤訊息代表,在 storyboard 中有一個 UIView 與上面 UIView 間距是 0
2.   根據錯誤訊息找出元件
      (1) 選擇 storyboard 並切換到 " show the version editor " 模式
      (2) 搜尋一下上述 constraint value,然後往上找一下看是哪個元件,並搭配錯誤訊息中元件種類判斷一下可能的元件,接著看看元件的其他屬性,其中 " userLabel " 就是元件在 storyboard 中的名稱

      (3) 再往上看一點,可看到綠色註解,是 xcode 產生的註解,可看出元件再哪個 ViewController


      (4) 切換回 " show the standard editor " ( 檢視 UI )


      (5) 用剛剛的線索找到元件


3.   修正 constraint value
      (1) 選擇 constraint 並切換到 " Interface Builder " 的 " connection inspector ",查看是否與程式碼連結

      (2) 切換回 controller.m,在程式碼中尋找剛剛的連結 ( 有聯結 storyboard 的宣告,前面會有黑點點 ),查詢一下看哪裡會變更這個 constraint value,確認一下計算公式是否正確,constraint value 變更後是否會與其他 constraint value 發生衝突


References