Làm cách nào để bẫy trên UIViewAlertForUnsatisfiableConstraint?


234

Tôi thấy một lỗi xuất hiện trong nhật ký trình gỡ lỗi của mình:

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.

Làm thế nào để tôi bẫy vào cuộc gọi đó? Nó không xuất hiện ở bất cứ đâu trong mã của tôi.

Ảnh chụp màn hình1


Trong 9 trên 10 trường hợp: điều này chỉ do: đối với một số chế độ xem hoặc mục trên bảng phân cảnh yoru, bạn bỏ chọn "Đã cài đặt". . Thông thường, giải pháp chỉ đơn giản là xóa các mục bạn đã quên, đó là ngồi xung quanh "chưa cài đặt" - chỉ cần xóa chúng.
Fattie

Câu trả lời:


442

Đây bài giúp tôi RẤT NHIỀU !

Tôi đã thêm điểm dừng biểu tượng của UIViewAlertForUnsatisfiableConstraint với hành động được đề xuất:

Dự án Obj-C

po [[UIWindow keyWindow] _autolayoutTrace]

Điểm dừng tượng trưng với hành động tùy chỉnh trong dự án Objective-C

Dự án Swift

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

Điểm dừng tượng trưng với hành động tùy chỉnh

Với gợi ý này, nhật ký trở nên chi tiết hơn và tôi dễ dàng xác định chế độ xem nào bị ràng buộc hơn.

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

Sau đó, tôi tạm dừng thực thi Tạm ngừng và tôi đã thay đổi màu nền của khung nhìn có vấn đề bằng lệnh (thay thế 0x7f88a8cc2050bằng địa chỉ bộ nhớ của đối tượng của bạn ) ...

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

... Và kết quả thật tuyệt vời!

Xem gợi ý

Đơn giản là tuyệt vời! Hy vọng nó giúp.


3
@iAnurag Bạn có thể chạy các lệnh trong vùng giao diện điều khiển, khi quá trình thực thi bị tạm dừng.
Thomás Calmon

2
@TomCalmon Tôi cũng làm như vậy ... nhưng nó hiển thị lỗi sau rror: Execution was interrupted, reason: EXC_BAD_ACCESS (code=1, address=0x7f88a8cc2050). The process has been returned to the state before expression evaluation.
iAnurag

2
expr -l objc++ -O -- [[UIWindow keyWindow] _autolayoutTrace]trả lại nilcho tôi
Igor Andreev

2
Đảm bảo bạn thay 0x7f88a8cc2050 bằng địa chỉ bộ nhớ của đối tượng và chạy lệnh trong bàn điều khiển khi thực thi tạm dừng.
Tom Howard

3
Không thể tin được. Mẹo tuyệt vời ở đây, hoàn toàn giúp tôi đi thẳng vào vấn đề. Khi mục được đổi thành màu đỏ, hãy tiếp tục thực hiện nếu có thể và bạn sẽ thấy phần nổi bật.
Aaron

255

Bạn sẽ muốn thêm một Symbolic Breakpoint. Apple cung cấp một hướng dẫn tuyệt vời về cách làm điều này.

  1. Mở Bộ điều hướng Breakpoint cmd+7( cmd+8trong Xcode 9)
  2. Nhấp vào Addnút ở phía dưới bên trái
  3. Lựa chọn Add Symbolic Breakpoint...
  4. Nơi nó nói Symbolchỉ cần gõ vàoUIViewAlertForUnsatisfiableConstraints

Bạn cũng có thể coi nó như bất kỳ điểm dừng nào khác, bật và tắt, thêm hành động hoặc thông báo nhật ký.


55
Tôi chỉ không hiểu làm thế nào tôi có thể gỡ lỗi vấn đề tốt hơn với gợi ý này. Tôi đã thêm một điểm dừng tượng trưng nhưng nó vẫn không cung cấp cho tôi đủ thông tin về vấn đề. Cách duy nhất là cố gắng đọc từng dòng một và hiểu nguyên nhân gây ra sự cố .... nếu không, hãy xóa các ràng buộc và thêm chúng cùng với Bản xem trước trong chế độ xem thường xuyên sẽ giúp ích nhiều nhất!
Alex Cio

11
Điều này có thể giúp có thêm thông tin sau khi dừng tại điểm dừng: staxmanade.com/2015/06/debugging-ios-autolayout-issues
fabb 24/07/2015

1
Chỉ cần thêm rằng bây giờ bạn có thể cung cấp định danh cho các ràng buộc trực tiếp trong IB để khi bạn gỡ lỗi chúng, đó là tên bạn sẽ thấy.
Đánh dấu A. Donohoe

2
(theo dõi trên @MarqueIV) NSLayoutConstraintđã có một identifiertài sản kể từ iOS 7 - Xcode 7 trở lên , có thể được đặt cả từ Bảng phân cảnh IB cũng từ mã. Bằng cách đặt mã định danh, bạn có thể phân biệt dễ dàng hơn giữa các ràng buộc do hệ thống tạo và người dùng tạo trong nhật ký gỡ lỗi, ví dụ: myConstraint.identifier = "centered image"(nguồn & ví dụ: useyourloaf.com/blog/USE-identifier-to-debug-autolayout )
PDK

@AlexCio Nó giúp như thế nào? Ít nhất nó làm là nó dừng lại tại thời điểm nó xảy ra. Nó đưa ra dấu vết ngăn xếp nơi bạn có thể quay lại và tìm nguồn gốc ...
Honey

10

Làm theo lời khuyên của Stephen và cố gắng gỡ lỗi mã và whoa! nó đã làm việc. Câu trả lời nằm trong chính thông báo gỡ lỗi.

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

Dòng trên cho bạn biết rằng thời gian chạy đã hoạt động bằng cách loại bỏ ràng buộc này. Có thể bạn không cần Khoảng cách ngang trên nút của mình (MPKnockoutButton). Khi bạn xóa ràng buộc này, nó sẽ không khiếu nại trong thời gian chạy và bạn sẽ có hành vi mong muốn.


3
Trình biên dịch? Bạn có nghĩa là thời gian chạy? Trình biên dịch đã không loại bỏ các ràng buộc. Trình biên dịch để nó ở đó cho thời gian chạy để xử lý, do đó "phục hồi bằng cách phá vỡ ràng buộc" trong thời gian chạy .
drhr

Vâng, tôi có nghĩa là thời gian chạy
Sargetroup

2

Bất cứ khi nào tôi cố gắng loại bỏ các ràng buộc mà hệ thống phải phá vỡ, các ràng buộc của tôi không còn đủ để đáp ứng IB (tức là "các ràng buộc bị thiếu" hiển thị trong IB, có nghĩa là chúng chưa hoàn chỉnh và sẽ không được sử dụng). Tôi thực sự đã khắc phục điều này bằng cách đặt ràng buộc mà nó muốn phá vỡ ở mức ưu tiên thấp, điều này (và đây là một giả định) cho phép hệ thống phá vỡ ràng buộc một cách duyên dáng. Đây có thể không phải là giải pháp tốt nhất, nhưng nó đã giải quyết vấn đề của tôi và các ràng buộc kết quả đã hoạt động hoàn hảo.


2
Thông thường, đó là một tình huống mà bạn muốn sử dụng một ràng buộc giữ chỗ được loại bỏ trong thời gian chạy. Để tạo một ràng buộc một ràng buộc giữ chỗ, hãy đi đến trình kiểm tra ràng buộc và nhấp vào "Xóa tại thời điểm xây dựng". Lưu ý cách biểu tượng ràng buộc I-tia trong vùng vẽ IB chuyển từ màu xanh sang màu xám để biểu thị điều này.
spencery2

1
Tôi gặp vấn đề tương tự. Khi tôi loại bỏ các ràng buộc bị hỏng thiết kế của tôi đã phá vỡ. Vì vậy, tôi đặt ưu tiên thành trung bình.
Jeremy Piednoel
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.