小ネタを書きます。
はじめに
AutoLayoutを使用したアプリで、実行時に以下のようなエラーログが出る時がたまにあります。
2016-12-09 14:43:14.502 ViewTest[19217:700173] Unable to simultaneously satisfy constraints:
(
"<NSLayoutConstraint:0x618000086860 H:[NSButton:0x618000140840'Button'(196)]>",
"<NSLayoutConstraint:0x618000086900 H:[NSButton:0x618000140840'Button'(<=30)]>"
)
Will attempt to recover by breaking constraint
<NSLayoutConstraint:0x618000086900 H:[NSButton:0x618000140840'Button'(<=30)]>
「設定してる制約を同時に満たすことができないよ」って言われているんですけど、たまーにstoryboard見ても何が原因かすぐわからなかったりすることがあると思います。
macOSアプリならこのような場合に、以下のように問題部分が可視化できます。
画像↑のオレンジの矢印部分をクリックするとコンソールに以下のようなログが出力されるのでこれをもとにデバッグします。
2016-12-09 15:06:54.303 ViewTest[19217:700173] Clicked on overlapping visualized constraints: (
"<NSLayoutConstraint:0x618000086860 H:[NSButton:0x618000140840'Button'(196)]> (Actual Distance - pixels):196",
"<NSLayoutConstraint:0x618000086900 H:[NSButton:0x618000140840'Button'(<=30)]> (Actual Distance - pixels):196"
)
これはボタンの長さが196pxと30px未満の制約がそれぞれあり、ぶつかってるよと言っています。
やり方
以下の一文をapplicationDidFinishLaunching
にでも追加します。
func applicationDidFinishLaunching(_ aNotification: Notification) {
UserDefaults.standard.set(true, forKey: "NSConstraintBasedLayoutVisualizeMutuallyExclusiveConstraints")
}
以上。
補足
この記事の一番上のエラーログの続きに以下の記載があります。
Set the NSUserDefault NSConstraintBasedLayoutVisualizeMutuallyExclusiveConstraints to YES to have -[NSWindow visualizeConstraints:] automatically called when this happens. And/or, break on objc_exception_throw to catch this in the debugger.
要はNSWindow
にvisualizeConstraints:
というメソッドがあり、ウィンドウに制約を渡すと可視化できます。
NSConstraintBasedLayoutVisualizeMutuallyExclusiveConstraints
をtrueにすると、問題のViewが表示された時に自動でvisualizeConstraints
を呼びます
とあります。