티스토리 뷰
[iOS 오토레이아웃 가이드] Debugging Auto Layout - Debugging Tricks and Tips
Understanding the Logs
View의 제약조건에 관한 정보는 콘솔에 출력됩니다. unsatisfiable layout이 있거나 constraintAffectingLayoutForAxix(Orientation)을 썼을 때 콘솔에 출력됩니다. 다음은 예입니다.
2015-08-26 14:27:54.790 Auto Layout Cookbook[10040:1906606] 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:0x7a87b000 H:[UILabel:0x7a8724b0'Name'(>=400)]>",
"<NSLayoutConstraint:0x7a895e30 UILabel:0x7a8724b0'Name'.leading == UIView:0x7a887ee0.leadingMargin>",
"<NSLayoutConstraint:0x7a886d20 H:[UILabel:0x7a8724b0'Name']-(NSSpace(8))-[UITextField:0x7a88cff0]>",
"<NSLayoutConstraint:0x7a87b2e0 UITextField:0x7a88cff0.trailing == UIView:0x7a887ee0.trailingMargin>",
"<NSLayoutConstraint:0x7ac7c430 'UIView-Encapsulated-Layout-Width' H:[UIView:0x7a887ee0(320)]>"
)
Will attempt to recover by breaking constraint
<NSLayoutConstraint:0x7a87b000 H:[UILabel:0x7a8724b0'Name'(>=400)]>
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.
콘솔에 찍힌 메시지들은 Visual Format Language를 사용합니다.
에러에는 5개의 충돌하는 제약조건이 있습니다. 모든 제약조건이 동시에 적용될 수 없습니다. 하나를 삭제하거나 하나를 optional constraint으로 만들면 해결됩니다.
뷰 계층이 비교적 쉽습니다. 슈퍼뷰에 label과 text field하나 밖에 없습니다. 충돌하는 제약조건을 보면 다음과 같습니다.
The label’s width is greater than or equal to 400 points.
The label’s leading edge is equal to the superview’s leading margin.
There is an 8-point space between the label and the text field.
The text field’s trailing edge is equal to the superview’s trailing margin.
The superview’s width is set to 320 points.
시스템은 레이블의 width 제약조건을 깨고 레이아웃을 만들려고 합니다. 그리고 마지막 제약조건은 system이 자동으로 만든 거라서 바꿀 수 없습니다. 게다가 첫 번째 제약조건과 충돌합니다. 해결하는 방법은 여러가지가 있겠지만 굳이 삭제하지 않고 priority를 999로만 낮춰도 됩니다.
Adding Identifiers to the Logs
에러메시지에서 제약조건을 쉽게 찾기 위해서 제약조건에 identifier를 줄 수 있습니다. text를 가진 뷰는 text가 identifier가 될 수 있습니다.
2015-08-26 14:29:32.870 Auto Layout Cookbook[10208:1918826] 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:0x7b58bac0 'Label Leading' UILabel:0x7b58b040'Name'.leading == UIView:0x7b590790.leadingMargin>",
"<NSLayoutConstraint:0x7b56d020 'Label Width' H:[UILabel:0x7b58b040'Name'(>=400)]>",
"<NSLayoutConstraint:0x7b58baf0 'Space Between Controls' H:[UILabel:0x7b58b040'Name']-(NSSpace(8))-[UITextField:0x7b589490]>",
"<NSLayoutConstraint:0x7b51cb10 'Text Field Trailing' UITextField:0x7b589490.trailing == UIView:0x7b590790.trailingMargin>",
"<NSLayoutConstraint:0x7b0758c0 'UIView-Encapsulated-Layout-Width' H:[UIView:0x7b590790(320)]>"
)
Will attempt to recover by breaking constraint
<NSLayoutConstraint:0x7b56d020 'Label Width' H:[UILabel:0x7b58b040'Name'(>=400)]>
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.
Visualizing Views and Constraints
Edit - canvas - show layout rectangles를 하면 다음과 같이 볼 수 있습니다. 뷰의 사이즈와 baseline을 한 눈에 확인 할 수 있습니다.
또한 앱을 실행하면 다음과 같은 화면이 나오는데 빨간색으로 표시된 버튼을 누르면 뷰계층을 볼 수 있습니다.
또한 editor - show clipped content는 뷰의 위치를 보여주고 show constraint는 뷰의 걸려있는 제약조건을 볼 수 있습니다.
Understanding Edge Cases
- 오토레이아웃은 뷰의 aligment rectangles를 기반으로 뷰를 위치 시킵니다. 뷰의 frame이 아니라. 대부분 이 둘을 같습니다. badge와 같은 뷰는 custom alignment rectangle를 가집니다
https://developer.apple.com/documentation/uikit/uiview/1622576-alignmentrect
그래서 transform을 이용해서 뷰의 사이즈를 조정하거나 돌리거나 제거해도 오토레이아웃에는 영향이 없습니다.
- 뷰 bounds 밖으로 내용이 나올 때는 clipsToBounds속성을 true로
- baseline은 뷰가 intrinsic content height를 가질 때만 가능
- 제약조건의 우선순위는 글로벌이라서 하위뷰에 속해 있더라도 가능
- aspect ratio는 height와 width 2개를 동시에 조절하므로 조심