Căn giữa X của lượt xem phụ trong chế độ tự động trả tiền cho thấy "không chuẩn bị cho sự ràng buộc"


82

Tôi có một lớp con UIView tùy chỉnh đang được khởi tạo thông qua một nib.

Trong đó -awakeFromNib, tôi đang tạo một chế độ xem phụ và cố gắng tập trung nó vào chế độ xem siêu cao của nó.

[self setInteralView: [[UIView alloc] init]];
[[self internalView] addConstraint: [NSLayoutConstraint constraintWithItem: [self internalView]
                                                                 attribute: NSLayoutAttributeCenterX
                                                                 relatedBy: NSLayoutRelationEqual
                                                                    toItem: self
                                                                 attribute: NSLayoutAttributeCenterX
                                                                multiplier: 1
                                                                  constant: 0]];

Điều này bị hỏng và gây ra kết quả sau:

2013-08-11 17:58:29.628 MyApp[32414:a0b] The view hierarchy is not prepared for the constraint: <NSLayoutConstraint:0xc1dcc80 UIView:0xc132a40.centerX == MyView:0xc1315a0.centerX>
    When added to a view, the constraint's items must be descendants of that view (or the view itself). This will crash if the constraint needs to be resolved before the view hierarchy is assembled. Break on -[UIView _viewHierarchyUnpreparedForConstraint:] to debug.
2013-08-11 17:58:29.630 MyApp[32414:a0b] View hierarchy unprepared for constraint.
    Constraint: <NSLayoutConstraint:0xc1dcc80 UIView:0xc132a40.centerX == MyView:0xc1315a0.centerX>
    Container hierarchy: 
<UIView: 0xc132a40; frame = (0 0; 0 0); clipsToBounds = YES; layer = <CALayer: 0xc132bc0>>
    View not found in container hierarchy: <MyView: 0xc1315a0; frame = (-128 -118; 576 804); layer = <CALayer: 0xc131710>>
    That view's superview: <UIView: 0xc131a70; frame = (0 0; 320 568); autoresize = W+H; layer = <CALayer: 0xc131b50>>

Câu trả lời:


95

Khi lỗi nêu rõ, bạn phải thêm ràng buộc vào một dạng xem sao cho các dạng xem liên quan đến ràng buộc là dạng xem bạn đang thêm nó vào hoặc một dạng xem con của dạng xem đó. Trong trường hợp mã của bạn ở trên, bạn nên thêm ràng buộc đó vào self, thay vì [self internalView]. Lý do nó không hoạt động như được viết là một trong những khung nhìn liên quan đến ràng buộc ( self) không nằm trong hệ thống phân cấp chế độ xem nếu bạn chỉ xem xét [self internalView]và bên dưới).

Để biết thêm chi tiết, hãy xem phần thảo luận của tài liệu về addConstraint:phương pháp này.

Đây là dòng mã của bạn, được sửa theo cách tôi đề xuất:

UIView* internalView = [[UIView alloc] initWithFrame:CGRectZero];
internalView.translatesAutoresizingMaskIntoConstraints = NO;
[self setInternalView:internalView];

[self addConstraint: [NSLayoutConstraint constraintWithItem: [self internalMapView]
                                         attribute: NSLayoutAttributeCenterX
                                         relatedBy: NSLayoutRelationEqual
                                         toItem: self
                                         attribute: NSLayoutAttributeCenterX
                                         multiplier: 1
                                         constant: 0]];

Điều đó mang lại cho tôi một lỗi tuyên bố Unable to simultaneously satisfy constraints. Probably at least one of the constraints in the following list is one you don't want.Và sau đó nó phá vỡ<NSLayoutConstraint:0x126ad4c0 UIView:0xadd2e20.centerX == MyView:0xadd19b0.centerX>
Patrick Perini

1
Nhiều khả năng là do bạn đã không tắt tính năng dịch mặt nạ tự động thay đổi kích thước thành các ràng buộc. Tôi sẽ cập nhật mã của mình ở trên để làm như vậy. Có thể bạn cũng sẽ cần thêm các ràng buộc về chiều rộng / chiều cao để nó hiển thị, và tôi khuyên bạn nên thêm một ràng buộc vào tâm Y hoặc một số loại ràng buộc trên / dưới cho bản thân để làm cho bố cục được xác định rõ ràng.
Charles A.

vì vậy bạn không thể có bố cục như @"V:|[v]|":? vì điều này sẽ đề cập đến một superview?
Sam,

1
@Sam Đó là một ràng buộc hợp lệ, nhưng nó sẽ không căn giữa chế độ xem được đại diện bởi [v]nó sẽ cung cấp cho bạn các ràng buộc trên cùng và dưới cùng của kích thước tiêu chuẩn giữa [v]các cạnh trên và dưới của nó và của superview. Bạn cũng sẽ phải thêm nó vào superview, tôi tin.
Charles A.

8
Một quy tắc ngón tay cái đơn giản: Bất kỳ ràng buộc nào liên quan đến kích thước của một khung nhìn đều phải được thêm vào cùng một khung nhìn và bất kỳ ràng buộc nào liên quan đến vị trí của nó phải được thêm vào cha của nó.
Deepak GM

117

Đối với những người khác đến đây: Tôi gặp lỗi này vì tôi đã thêm các ràng buộc trước khi thêm các chế độ xem phụ vào cấu trúc phân cấp.


Cảm ơn, bạn đã tiết kiệm cho tôi rất nhiều thời gian!
Stas

Đây là lý do phổ biến nhất cho sự thất bại này mà tôi nhận thấy cho đến nay.
Ayan Sengupta

chính xác và khi bạn làm điều đó constraintWithItem: youViewthì mục đó không tồn tại trong đó!
Nazir

36

Câu trả lời ngắn gọn : hoán đổi chế độ xem phụ huynh và trẻ em.
Giả sử selflà chế độ xem gốc:

  • tệ :[subview addConstraint [NSLayoutConstraint constraintWithItem:self...

  • tốt :[self addConstraint [NSLayoutConstraint constraintWithItem:subview...


Nhanh

subview.translatesAutoresizingMaskIntoConstraints = false
self.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat(
    "H:|-0-[subview]-0-|",
    options: .DirectionLeadingToTrailing,
    metrics: nil,
    views: ["subview":subview]))

Ob-C


10

Mẹo bổ sung:

Tôi có một Ứng dụng mới được phát triển chạy tốt trên iOS7 nhưng gặp lỗi trên iOS8 "Hệ thống phân cấp chế độ xem không được chuẩn bị cho ràng buộc".

Đọc một số bài đăng khác nói rằng các khung nhìn (phụ) cần được thêm vào trước khi tạo ràng buộc. Tôi đã làm điều đó nhưng vẫn bị lỗi.

Sau đó, tôi đã tìm ra rằng tôi nên tạo các ràng buộc trong - (void) viewDidAppear thay vì viewDidLoad


2
Khi viewDidAppear()được gọi, chế độ xem đã hiển thị cho người dùng. Nếu sửa đổi các ràng buộc thì trước đó, trong viewWillLayoutSubviews(). Lại thêm một vòng đời ở đây: medium.com/@SergiGracia/...
maganap

6

Đây là một câu hỏi cũ nhưng tôi muốn chỉ ra dòng này từ tài liệu:

Khi phát triển cho iOS 8.0 trở lên, hãy đặt thuộc tính isActive của ràng buộc thành true thay vì gọi trực tiếp phương thức addConstraint (_ :). Thuộc tính isActive tự động thêm và xóa ràng buộc khỏi chế độ xem chính xác.

Ít nhất, điều này sẽ loại bỏ một điểm thất bại vì bạn không còn phải lo lắng về việc gọi addConstraint ở chế độ xem sai


2

Trong trường hợp của tôi, nó đã được giải quyết bằng cách sử dụng chế độ xem gốc làm vùng chứa các ràng buộc thay vì chế độ xem hiện được tạo.

Ý tôi là, sử dụng bên trong viewController

view.addConstraints([leftConstraintImage, topConstraintImage]) thay vì imageView.addConstraints...


1

Như @CharlesA đã chỉ ra trong câu trả lời của mình, vấn đề là chế độ xem bạn đang thêm không nằm trong phân cấp chế độ xem thích hợp. Câu trả lời của anh ấy là một câu trả lời hay, nhưng tôi sẽ trình bày một số chi tiết cho một trường hợp sử dụng cụ thể đã gây ra vấn đề này cho tôi:

Tôi đã xảy ra điều này khi cố gắng thêm các ràng buộc vào một chế độ xem có bộ điều khiển chế độ xem mà tôi đã khởi tạo bằng cách sử dụng instantiateViewControllerWithIdentifier. Để giải quyết vấn đề, tôi đã sử dụng [childViewController didMoveToParentViewController:self]. Điều này đã thêm chế độ xem vào hệ thống phân cấp chế độ xem được tham chiếu bởi ràng buộc của tôi.


0

Đầu tiên hãy thêm subView của bạn và sau đó thêm các ràng buộc của bạn như thế này

addSubview(yourSubViewHere)
yourSubViewHere.translatesAutoresizingMaskIntoConstraints = false

addConstraint(NSLayoutConstraint(....
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.