자동 레이아웃에서 하위 뷰의 X를 중앙에 배치하면 "제약 조건에 대해 준비되지 않음"이 발생합니다.


82

펜촉을 통해 초기화되는 사용자 지정 UIView 하위 클래스가 있습니다.

에서가 -awakeFromNib, 나 하위 뷰를 생성하고 수퍼에 중심을 시도하고있다.

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

이로 인해 중단되고 다음과 같은 출력이 발생합니다.

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>>

답변:


95

오류가 언급했듯이 제약 조건과 관련된 뷰가 뷰에 추가되는 뷰 또는 해당 뷰의 하위 뷰가되도록 제약 조건을 뷰에 추가해야합니다. 위 코드의 경우 .이 self아닌에 해당 제약 조건을 추가해야합니다 [self internalView]. 작성된대로 작동하지 않는 이유는 제약 조건 ( self) 과 관련된 뷰 중 하나가 [self internalView]아래 만 고려할 경우 뷰 계층 구조에 없기 때문입니다 .

자세한 내용 은 방법 에 대한 문서토론 섹션을 참조하십시오 addConstraint:.

내가 제안한대로 수정 된 코드 줄은 다음과 같습니다.

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]];

그것은 나에게 주장하는 오류를 준다. Unable to simultaneously satisfy constraints. Probably at least one of the constraints in the following list is one you don't want.그리고 그것은 부러진다<NSLayoutConstraint:0x126ad4c0 UIView:0xadd2e20.centerX == MyView:0xadd19b0.centerX>
Patrick Perini

1
자동 크기 조정 마스크를 제약 조건으로 변환하는 기능을 비활성화하지 않았기 때문일 가능성이 높습니다. 이를 위해 위의 코드를 업데이트하겠습니다. 당신은 또한 그것이 보이도록 너비 / 높이 제약을 추가 할 필요가있을 것이고, 레이아웃을 잘 정의하기 위해 중앙 Y에 제약을 추가하거나 self에 일종의 상 / 하 제약을 추가하는 것이 좋습니다.
Charles A.

: 그래서 당신은 같은 레이아웃을 가지고 캔트 @"V:|[v]|"? 이것은 수퍼 뷰를 의미할까요?
Sam

1
@Sam 유효한 제약 조건이지만으로 표시되는 뷰를 중앙에 배치하지는 않습니다. 의 상단 및 하단 가장자리와 수퍼 뷰 [v]사이의 표준 크기의 상단 및 하단 제약 조건을 제공합니다 [v]. 수퍼 뷰에 추가해야 할 것입니다.
Charles A.

8
간단한 규칙 : 뷰의 크기와 관련된 모든 제약은 동일한 뷰에 추가되어야하며 위치와 관련된 제약은 부모에 추가되어야합니다.
Deepak GM

117

여기에 오는 다른 사람들을 위해 : 계층에 하위 뷰를 추가하기 전에 제약 조건을 추가했기 때문에이 오류가 발생했습니다.


감사합니다. 시간을 많이 절약 해 주셨습니다!
Stas

이것이 제가 지금까지 발견 한 가장 일반적인 실패 원인입니다.
Ayan Sengupta

정확히 그리고 당신이 그것을 할 때 constraintWithItem: youView항목이 존재하지 않습니다!
Nazir 2016

36

짧은 답변 : 스왑 부모와 자식보기. 상위 뷰
라고 가정 self합니다.

  • 나쁨 :[subview addConstraint [NSLayoutConstraint constraintWithItem:self...

  • 좋다 :[self addConstraint [NSLayoutConstraint constraintWithItem:subview...


빠른

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

Obj-C


10

추가 팁 :

iOS7에서 잘 실행되는 새로 개발 된 앱이 있지만 iOS8에서 "The view hierarchy is not ready for the constraint"라는 오류가 발생합니다.

다른 게시물을 읽으면 제약 조건을 만들기 전에 (하위)보기를 추가해야한다고 말했습니다. 나는 그것을했지만 여전히 오류가 있습니다.

그런 다음 viewDidLoad 대신-(void) viewDidAppear 아래에 제약 조건을 만들어야한다는 것을 알아 냈습니다.


2
viewDidAppear()호출 뷰는 이미 사용자가 볼 수 있습니다. 제약 조건을 수정하는 경우 viewWillLayoutSubviews(). 더 많은 수명주기 : medium.com/@SergiGracia/…
maganap

6

이것은 오래된 질문이지만 문서에서 다음 줄을 지적하고 싶습니다.

iOS 8.0 이상용으로 개발하는 경우 addConstraint (_ :) 메서드를 직접 호출하는 대신 제약 조건의 isActive 속성을 true로 설정합니다. isActive 속성은 올바른보기에서 제약 조건을 자동으로 추가하고 제거합니다.

적어도 이것은 잘못된 뷰에서 addConstraint를 호출하는 것에 대해 더 이상 걱정할 필요가 없기 때문에 하나의 실패 지점을 제거합니다.


2

제 경우에는 현재 생성 된 뷰 대신 제약 조건의 컨테이너로 루트 뷰를 사용하여 해결되었습니다.

내 말은, viewController 내부에서 사용

view.addConstraints([leftConstraintImage, topConstraintImage]) 대신에 imageView.addConstraints...


1

@CharlesA가 그의 대답에서 지적했듯이 문제는 추가하는 뷰가 적절한 뷰 계층 구조에 있지 않다는 것입니다. 그의 대답은 좋은 대답이지만이 문제를 일으킨 특정 사용 사례에 대해 자세히 설명하겠습니다.

뷰 컨트롤러를 사용하여 인스턴스화 한 뷰에 제약 조건을 추가하려고 할 때 이런 일이 발생했습니다 instantiateViewControllerWithIdentifier. 문제를 해결하기 위해 [childViewController didMoveToParentViewController:self]. 이것은 내 제약 조건에서 참조하는 뷰 계층 구조에 뷰를 추가했습니다.


0

먼저 subView를 추가하고 다음과 같은 제약 조건을 추가하십시오.

addSubview(yourSubViewHere)
yourSubViewHere.translatesAutoresizingMaskIntoConstraints = false

addConstraint(NSLayoutConstraint(....
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.