UIViewAlertForUnsatisfiableConstraintsでトラップする方法?


234

デバッガーログにエラーが表示されます。

Will attempt to recover by breaking constraint 
<NSLayoutConstraint:0x191f0920 H:[MPKnockoutButton:0x17a876b0]-(34)-[MPDetailSlider:0x17a8bc50](LTR)>

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.

その通話をどうやってトラップするのですか?それは私のコードのどこにも現れません。

スクリーンショット1


10ケース中9ケース:これは次の原因により発生します:yoruストーリーボードの一部のビューまたはアイテムで、[インストール済み]をオフにします。(たとえば、開発ボタンなど、必要のなくなったものだけです。)一般に、「インストールされていない」を適切に処理します。インストールされていない項目がないと、制約がそのまま残り、意味がなくなります。多くの場合、解決策は、「インストールされていない」の周りにある、忘れてしまったアイテムを単に削除することです-削除するだけです。
Fattie 2017

回答:


442

この投稿は私をたくさん助けてくれまし

提案されたアクションでUIViewAlertForUnsatisfiableConstraintsシンボリックブレークポイントを追加しました。

Obj-Cプロジェクト

po [[UIWindow keyWindow] _autolayoutTrace]

Objective-Cプロジェクトのカスタムアクションを持つシンボリックブレークポイント

Swiftプロジェクト

expr -l objc++ -O -- [[UIWindow keyWindow] _autolayoutTrace]

カスタムアクションを備えたシンボリックブレークポイント

このヒントにより、ログがより詳細になり、どのビューが制約を破っていたかを簡単に特定できました。

UIWindow:0x7f88a8e4a4a0
|   UILayoutContainerView:0x7f88a8f23b70
|   |   UINavigationTransitionView:0x7f88a8ca1970
|   |   |   UIViewControllerWrapperView:0x7f88a8f2aab0
|   |   |   |   UIView:0x7f88a8ca2880
|   |   |   |   |   *UIView:0x7f88a8ca2a10
|   |   |   |   |   |   *UIButton:0x7f88a8c98820'Archived'
|   |   |   |   |   |   |   UIButtonLabel:0x7f88a8cb0e30'Archived'
|   |   |   |   |   |   *UIButton:0x7f88a8ca22d0'Download'
|   |   |   |   |   |   |   UIButtonLabel:0x7f88a8cb04e0'Download'
|   |   |   |   |   |   *UIButton:0x7f88a8ca1580'Deleted'
|   |   |   |   |   |   |   UIButtonLabel:0x7f88a8caf100'Deleted'
|   |   |   |   |   *UIView:0x7f88a8ca33e0
|   |   |   |   |   *_UILayoutGuide:0x7f88a8ca35b0
|   |   |   |   |   *_UILayoutGuide:0x7f88a8ca4090
|   |   |   |   |   _UIPageViewControllerContentView:0x7f88a8f1a390
|   |   |   |   |   |   _UIQueuingScrollView:0x7f88aa031c00
|   |   |   |   |   |   |   UIView:0x7f88a8f38070
|   |   |   |   |   |   |   UIView:0x7f88a8f381e0
|   |   |   |   |   |   |   |   UIView:0x7f88a8f39fa0, MISSING HOST CONSTRAINTS
|   |   |   |   |   |   |   |   |   *UIButton:0x7f88a8cb9bf0'Retrieve data'- AMBIGUOUS LAYOUT for UIButton:0x7f88a8cb9bf0'Retrieve data'.minX{id: 170}, UIButton:0x7f88a8cb9bf0'Retrieve data'.minY{id: 171}
|   |   |   |   |   |   |   |   |   *UIImageView:0x7f88a8f3ad80- AMBIGUOUS LAYOUT for UIImageView:0x7f88a8f3ad80.minX{id: 172}, UIImageView:0x7f88a8f3ad80.minY{id: 173}
|   |   |   |   |   |   |   |   |   *App.RecordInfoView:0x7f88a8cbe530- AMBIGUOUS LAYOUT for App.RecordInfoView:0x7f88a8cbe530.minX{id: 174}, App.RecordInfoView:0x7f88a8cbe530.minY{id: 175}, App.RecordInfoView:0x7f88a8cbe530.Width{id: 176}, App.RecordInfoView:0x7f88a8cbe530.Height{id: 177}
|   |   |   |   |   |   |   |   |   |   +UIView:0x7f88a8cc1d30- AMBIGUOUS LAYOUT for UIView:0x7f88a8cc1d30.minX{id: 178}, UIView:0x7f88a8cc1d30.minY{id: 179}, UIView:0x7f88a8cc1d30.Width{id: 180}, UIView:0x7f88a8cc1d30.Height{id: 181}
|   |   |   |   |   |   |   |   |   |   |   *UIView:0x7f88a8cc1ec0- AMBIGUOUS LAYOUT for UIView:0x7f88a8cc1ec0.minX{id: 153}, UIView:0x7f88a8cc1ec0.minY{id: 151}, UIView:0x7f88a8cc1ec0.Width{id: 154}, UIView:0x7f88a8cc1ec0.Height{id: 165}
|   |   |   |   |   |   |   |   |   |   |   |   *UIView:0x7f88a8e68e10- AMBIGUOUS LAYOUT for UIView:0x7f88a8e68e10.minX{id: 155}, UIView:0x7f88a8e68e10.minY{id: 150}, UIView:0x7f88a8e68e10.Width{id: 156}
|   |   |   |   |   |   |   |   |   |   |   |   *UIImageView:0x7f88a8e65de0- AMBIGUOUS LAYOUT for UIImageView:0x7f88a8e65de0.minX{id: 159}, UIImageView:0x7f88a8e65de0.minY{id: 182}
|   |   |   |   |   |   |   |   |   |   |   |   *UILabel:0x7f88a8e69080'8-6-2015'- AMBIGUOUS LAYOUT for UILabel:0x7f88a8e69080'8-6-2015'.minX{id: 183}, UILabel:0x7f88a8e69080'8-6-2015'.minY{id: 184}, UILabel:0x7f88a8e69080'8-6-2015'.Width{id: 185}
|   |   |   |   |   |   |   |   |   |   |   |   *UILabel:0x7f88a8cc0690'16:34'- AMBIGUOUS LAYOUT for UILabel:0x7f88a8cc0690'16:34'.minX{id: 186}, UILabel:0x7f88a8cc0690'16:34'.minY{id: 187}, UILabel:0x7f88a8cc0690'16:34'.Width{id: 188}, UILabel:0x7f88a8cc0690'16:34'.Height{id: 189}
|   |   |   |   |   |   |   |   |   |   |   |   *UIView:0x7f88a8cc2050- AMBIGUOUS LAYOUT for UIView:0x7f88a8cc2050.minX{id: 161}, UIView:0x7f88a8cc2050.minY{id: 166}, UIView:0x7f88a8cc2050.Width{id: 163}
|   |   |   |   |   |   |   |   |   |   |   |   *UIImageView:0x7f88a8e69d90- AMBIGUOUS LAYOUT for UIImageView:0x7f88a8e69d90.minX{id: 190}, UIImageView:0x7f88a8e69d90.minY{id: 191}, UIImageView:0x7f88a8e69d90.Width{id: 192}, UIImageView:0x7f88a8e69d90.Height{id: 193}
|   |   |   |   |   |   |   |   |   |   |   *UIView:0x7f88a8f3cc00
|   |   |   |   |   |   |   |   |   |   |   |   *UIView:0x7f88a8e618d0
|   |   |   |   |   |   |   |   |   |   |   |   *UIImageView:0x7f88a8e5ba10
|   |   |   |   |   |   |   |   |   |   |   |   *UIView:0x7f88a8f3cd70
|   |   |   |   |   |   |   |   |   |   |   |   *UIImageView:0x7f88a8e58e10
|   |   |   |   |   |   |   |   |   |   |   |   *UIImageView:0x7f88a8e5e7a0
|   |   |   |   |   |   |   |   |   |   |   |   *UIView:0x7f88a8f3cee0
|   |   |   |   |   |   |   |   |   |   |   *UIView:0x7f88a8f3dc70
|   |   |   |   |   |   |   |   |   |   |   |   *UIView:0x7f88a8e64dd0
|   |   |   |   |   |   |   |   |   |   |   |   *UILabel:0x7f88a8e65290'Average flow rate'
|   |   |   |   |   |   |   |   |   |   |   |   *UILabel:0x7f88a8e712d0'177.0 ml/s'
|   |   |   |   |   |   |   |   |   |   |   |   *UILabel:0x7f88a8c97150'1299.4'
|   |   |   |   |   |   |   |   |   |   |   |   *UIView:0x7f88a8f3dde0
|   |   |   |   |   |   |   |   |   |   |   |   *UILabel:0x7f88a8f3df50'Maximum flow rate'
|   |   |   |   |   |   |   |   |   |   |   |   *UILabel:0x7f88a8cbfdb0'371.6 ml/s'
|   |   |   |   |   |   |   |   |   |   |   |   *UILabel:0x7f88a8cc0230'873.5'
|   |   |   |   |   |   |   |   |   |   |   |   *UIView:0x7f88a8f3e2a0
|   |   |   |   |   |   |   |   |   |   |   |   *UILabel:0x7f88a8f3e410'Total volume'
|   |   |   |   |   |   |   |   |   |   |   |   *UILabel:0x7f88a8cc0f20'371.6 ml'
|   |   |   |   |   |   |   |   |   |   |   |   *UIView:0x7f88a8f3e870
|   |   |   |   |   |   |   |   |   |   |   |   *UILabel:0x7f88a8f3ea00'Time do max. flow'
|   |   |   |   |   |   |   |   |   |   |   |   *UILabel:0x7f88a8cc0ac0'3.6 s'
|   |   |   |   |   |   |   |   |   |   |   |   *UIView:0x7f88a8f3ee10
|   |   |   |   |   |   |   |   |   |   |   |   *UILabel:0x7f88a8f3efa0'Flow time'
|   |   |   |   |   |   |   |   |   |   |   |   *UILabel:0x7f88a8cbf980'2.1 s'
|   |   |   |   |   |   |   |   |   |   |   |   *UIView:0x7f88a8f3f3e0
|   |   |   |   |   |   |   |   |   |   |   |   *UILabel:0x7f88a8f3f570'Voiding time'
|   |   |   |   |   |   |   |   |   |   |   |   *UILabel:0x7f88a8cc17e0'3.5 s'
|   |   |   |   |   |   |   |   |   |   |   |   *UIView:0x7f88a8f3f9a0
|   |   |   |   |   |   |   |   |   |   |   |   *UILabel:0x7f88a8f3fb30'Voiding delay'
|   |   |   |   |   |   |   |   |   |   |   |   *UILabel:0x7f88a8cc1380'1.0 s'
|   |   |   |   |   |   |   |   |   |   |   |   *UIView:0x7f88a8e65000
|   |   |   |   |   |   |   |   |   |   |   |   *UIButton:0x7f88a8e52f20'Show'
|   |   |   |   |   |   |   |   |   |   |   |   *UIImageView:0x7f88a8e6e1d0
|   |   |   |   |   |   |   |   |   |   |   |   *UIButton:0x7f88a8e52c90'Send'
|   |   |   |   |   |   |   |   |   |   |   |   *UIImageView:0x7f88a8e61bb0
|   |   |   |   |   |   |   |   |   |   |   |   *UIButton:0x7f88a8e528e0'Delete'
|   |   |   |   |   |   |   |   |   |   |   |   *UIImageView:0x7f88a8e6b3f0
|   |   |   |   |   |   |   |   |   |   |   |   *UIView:0x7f88a8f3ff60
|   |   |   |   |   |   |   |   |   *UIActivityIndicatorView:0x7f88a8cba080
|   |   |   |   |   |   |   |   |   |   UIImageView:0x7f88a8cba700
|   |   |   |   |   |   |   |   |   *_UILayoutGuide:0x7f88a8cc3150
|   |   |   |   |   |   |   |   |   *_UILayoutGuide:0x7f88a8cc3b10
|   |   |   |   |   |   |   UIView:0x7f88a8f339c0
|   |   UINavigationBar:0x7f88a8c96810
|   |   |   _UINavigationBarBackground:0x7f88a8e45c00
|   |   |   |   UIImageView:0x7f88a8e46410
|   |   |   UINavigationItemView:0x7f88a8c97520'App'
|   |   |   |   UILabel:0x7f88a8c97cc0'App'
|   |   |   UINavigationButton:0x7f88a8e3e850
|   |   |   |   UIImageView:0x7f88a8e445b0
|   |   |   _UINavigationBarBackIndicatorView:0x7f88a8f2b530

Legend:
    * - is laid out with auto layout
    + - is laid out manually, but is represented in the layout engine because translatesAutoresizingMaskIntoConstraints = YES
     - layout engine host

次に、実行を一時停止し 一時停止 、問題のあるビューの背景色をコマンドで変更しました(もちろん、オブジェクトの0x7f88a8cc2050メモリアドレスに置き換えます)...

Obj-C

expr ((UIView *)0x7f88a8cc2050).backgroundColor = [UIColor redColor]

Swift 3.0

expr -l Swift -- import UIKit
expr -l Swift -- unsafeBitCast(0x7f88a8cc2050, to: UIView.self).backgroundColor = UIColor.red

...そしてその結果それは素晴らしかった!

ヒント付きビュー

ただ素晴らしい!それが役に立てば幸い。


3
@iAnurag実行が一時停止しているときに、コンソール領域でコマンドを実行できます。
トーマスCalmon

2
@TomCalmon私も同じことをしましたが、次のエラーが表示されます rror: Execution was interrupted, reason: EXC_BAD_ACCESS (code=1, address=0x7f88a8cc2050). The process has been returned to the state before expression evaluation.
iAnurag '13 / 07/13

2
expr -l objc++ -O -- [[UIWindow keyWindow] _autolayoutTrace]戻ってnil私のために
イゴール・アンドレエフ

2
必ず0x7f88a8cc2050をオブジェクトのメモリアドレスに置き換え、実行が一時停止したときにコンソールでコマンドを実行してください。
トムハワード

3
信じられない。ここでのヒントは、問題を直接解決するのに役立ちました。アイテムが赤に変更されたら、可能であれば実行を続行すると、ハイライトが表示されます。
アーロン

255

を追加する必要がありますSymbolic Breakpoint。Appleはこれを行う方法についての優れたガイドを提供しています。

  1. ブレークポイントナビゲーターを開きますcmd+7cmd+8Xcode 9の場合)
  2. Add左下のボタンをクリックしてください
  3. 選択する Add Symbolic Breakpoint...
  4. Symbol入力するだけと書いてあるところUIViewAlertForUnsatisfiableConstraints

また、他のブレークポイントと同様に扱い、オンとオフを切り替えたり、アクションを追加したり、メッセージをログに記録したりすることもできます。


55
このヒントで問題をよりよくデバッグする方法がわかりません。シンボリックブレークポイントを追加しましたが、それでも問題の情報が不十分です。唯一の方法は、1行ずつ読み取り、問題の原因を理解することです。それ以外の場合は、制約をクリアし、再度asisstentビューのプレビューと一緒に追加すると、最も効果的です。
Alex Cio 2015年

11
これは、ブレークポイントで停止した後に詳細情報を取得するのに役立つ可能性があります:staxmanade.com/2015/06/debugging-ios-autolayout-issues
fabb

1
これを追加するだけで、IBで制約に識別子を直接与えることができるので、それらをデバッグしているときに、それが表示される名前になります。
Mark A. Donohoe

2
(@MarqueIVのフォローアップ)にNSLayoutConstraintidentifier、iOS 7Xcode 7以降のプロパティがあり、IB Storyboardsとコードの両方から設定できます。識別子を設定することで、デバッグログでシステム生成の制約とユーザー生成の制約を簡単に区別できます。例myConstraint.identifier = "centered image"(ソースと例:useyourloaf.com/blog/using-identifiers-to-debug-autolayout
PDK

@AlexCioそれはどのように役立ちますか?少なくとも、発生した瞬間に一時停止するだけです。スタックトレースが得られ、バックトラックして原点を見つけることができます...
Honey

10

スティーブンのアドバイスに従い、コードとおっとをデバッグしようとしました!出来た。答えは、デバッグメッセージ自体にあります。

Will attempt to recover by breaking constraint NSLayoutConstraint:0x191f0920 H:[MPKnockoutButton:0x17a876b0]-(34)-[MPDetailSlider:0x17a8bc50](LTR)>

上記の行は、ランタイムがこの制約を削除することで機能したことを示しています。ボタン(MPKnockoutButton)に水平間隔が必要ない場合もあります。この制約をクリアすると、実行時に不満がなくなり、望ましい動作が得られます。


3
コンパイラー?あなたはランタイムを意味しますか?コンパイラーは制約を削除しませんでした。コンパイラーは、ランタイムが処理するためにそこに残したため、ランタイム中に「制約を壊すことによって回復する」。
15

ええ、ランタイムを意味しました
Sategroup、2015

2

システムが違反しなければならなかった制約を削除しようとすると、私の制約はIBを満たすのに十分ではありません(つまり、「欠けている制約」はIBに表示されます。つまり、制約が不完全で使用されません)。私は実際に、ブレークしたい制約を低い優先度に設定することでこれを回避しました(これは仮定です)ことで、システムは制約を適切に解除できます。それはおそらく最良の解決策ではありませんが、私の問題を解決し、結果として生じる制約は完全に機能しました。


2
通常、これは、実行時に削除されるプレースホルダー制約を使用したい状況です。制約をプレースホルダー制約にするには、制約インスペクターに移動し、[ビルド時に削除]をクリックします。これを示すために、IB作図領域の拘束Iビームシンボルが青から灰色に変わっていることに注目してください。
spencery2 2015

1
同じ問題がありました。壊れた制約を削除すると、デザインが壊れました。優先度を中に設定しました。
Jeremy Piednoel 16
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.