Debugging Autolayout in Xcode
Autolayout được apple giới thiệu từ IOS 6 (Xcode 6) và đã trở thành kỹ thuật không thể thiếu đối với các lập trình viên IOS. Việc vận dụng khả năng của autolayout tốt, giúp lập trình viên giải quyết bài toàn đa màn hình, và đơn giản hóa code xử lý trong controller. Trong quá trình sử dụng các lập ...
Autolayout được apple giới thiệu từ IOS 6 (Xcode 6) và đã trở thành kỹ thuật không thể thiếu đối với các lập trình viên IOS. Việc vận dụng khả năng của autolayout tốt, giúp lập trình viên giải quyết bài toàn đa màn hình, và đơn giản hóa code xử lý trong controller.
Trong quá trình sử dụng các lập trình viên ít nhất củng đã thấy log output ở màn hình debugger console như dưới đây:
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. ( "<NSLayoutConstraint:0x7f9487613cc0 H:[UIView:0x7f948762d820(560)]>", "<NSLayoutConstraint:0x7f948762c7d0 H:|-(20)-[UIView:0x7f948762d820] (Names: '|':UIView:0x7f948770e6c0 )>", "<NSLayoutConstraint:0x7f948762c820 H:[UIView:0x7f948762d820]-(20)-| (Names: '|':UIView:0x7f948770e6c0 )>", "<NSLayoutConstraint:0x7f948750c630 'UIView-Encapsulated-Layout-Width' H:[UIView:0x7f948770e6c0(375)]>" ) Will attempt to recover by breaking constraint <NSLayoutConstraint:0x7f9487613cc0 H:[UIView:0x7f948762d820(560)]> 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.
Vấn đề gì đang xảy ra ???.
Tại sao giao diện vẫn hiển thị như chúng ta muốn, nhưng debug console lại hiện thị warning.
Nguyên nhân
Giả dụ các bạn đọc bài này đã làm quen với autolayout, và có kiến thức cơ bản về nó.Thì chắc các bạn củng biết là, việc tạo các constraint cho các view và xcode tính toán các constraint đó để đưa ra vị trí View chủ yếu dựa theo công thức:
object1.property1 = (object2.property2 * multiplier) + constant value
Việc giải bài toán gồm nhiều biến để đưa ra 1 kết quá duy nhất đều do SDK xử lý, tuy nhiên sẽ có nhiều trường hợp xảy ra khi giải bài toán này.
- Không tính toán được kết quả dựa vào các công thức trên
- Dựa vào công thức trên SDK tính toán được duy nhất 1 kết quả.
- Các công thức conflict lẫn nhau, và đưa ra nhiều kết quả => dẫn đến warning trên console log như trên.
P/S : Khi gặp trường hợp này thì app vẫn chạy, và "hầu như" giao diện vẫn đúng như mình mong muốn.SDK sẽ cho 1 kết quả và hiện thị.Tester sẽ ko biết vấn đề xảy ra. Tuy nhiên, đối với developer thì code ko đc phép có warning, error hay có log console như trường hợp trên.
Sau đây mình đưa ra 1 số cách để giải quyết vấn đề trên:
Breakpoint
Thường thường lập trình viên chỉ chú ý đến nếu app crash mà ko quan tâm đến warning ,do đó thường bỏ qua nó.Và đối với warning autolayout thường khó phát hiện khi nào xảy ra, ở đâu. Do đó, cách đặt breakpoint sau đây sẽ giúp lập trình viên chú ý hơn đến lỗi warning này:
1 - Open the Breakpoint Navigator 2 - Click the Add button in the lower left 3 - Select Add Symbolic Breakpoint... 4 - Set Symbol = UIViewAlertForUnsatisfiableConstraints
Với thiết lập này, thì khi gặp vấn đề về autolayout, XCode sẽ break và point đến assembly code và memory addresses:
Tìm constraint bị lỗi
Đặt breakpoint chỉ chỉ ra rằng view đang bị lỗi layout, còn để tìm ra view bị lỗi thì các bạn chú ý đến đoạn code sau:
Will attempt to recover by breaking constraint <NSLayoutConstraint:0x7f936d724a30 H:[UIView:0x7f936d726320(560)]>
Với đoạn log trên , bạn chỉ biết được địa chỉ của view bị lỗi, nhưng chưa xác định constaint nào.
- Đặt Identifier cho constaint:
Open constaint detail và set Identifier có constaint bạn nghi ngờ :
Will attempt to recover by breaking constraint <NSLayoutConstraint:0x7f8f1a511ea0 'IdentifierWidth' H:[UIView:0x7f8f1a512000(560)]>
Với cách này bạn sẽ biết được constraint nào bị lỗi dưa theo identifer custom 2. Print address memory view:
(lldb) po $r15
Fix lỗi
Sau khi tìm đc view bị lỗi, thì công việc cuối cùng của bạn sẽ phải fix nó