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

펜촉을 통해 초기화되는 사용자 지정 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>>



답변

오류가 언급했듯이 제약 조건과 관련된 뷰가 뷰에 추가되는 뷰 또는 해당 뷰의 하위 뷰가되도록 제약 조건을 뷰에 추가해야합니다. 위 코드의 경우 .이 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]];


답변

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


답변

짧은 답변 : 스왑 부모와 자식보기. 상위 뷰
라고 가정 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


답변

추가 팁 :

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

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

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


답변

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

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

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


답변

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

내 말은, viewController 내부에서 사용

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


답변

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

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