[ios] 프로그래밍 방식으로 뷰를 만들 때 자동 레이아웃 제약 조건을 설정해야하는 위치

제약이 설정된 다른 예를 봅니다. 일부는 viewDidLoad/ loadView(하위보기가 추가 된 후) 에 설정합니다 . 다른 사람들 updateViewConstraints은에 의해 호출되는 메서드에서 설정합니다 viewDidAppear.

제약 조건을 설정하려고 updateViewContraints하면 레이아웃이 불안정해질 수 있습니다 (예 :보기가 나타나기 전에 약간의 지연). 또한이 방법을 사용하면 기존 제약 조건을 먼저 정리해야 [self.view [removeConstraints:self.view.constraints]합니까?



답변

viewDidLoad/에 제약 조건을 설정했습니다 loadView(iOS> = 6을 타겟팅하고 있습니다). updateViewConstraints제약 조건 값을 변경하는 데 유용합니다. 예를 들어 어떤 제약 조건이 화면의 방향에 따라 달라지는 경우 (나쁜 습관입니다) constant이 방법에서 변경할 수 있습니다 .

에 제약을 추가하는 viewDidLoad것은 39:22부터 시작하는 “iOS 및 OS X 용 자동 레이아웃 소개” (WWDC 2012) 세션에서 표시됩니다. 나는 그것이 강의 중에 말한 것 중 하나라고 생각하지만 문서에 포함되지는 않습니다.

업데이트 : View Controllers의 리소스 관리에서 제약 조건 설정에 대한 언급을 발견했습니다 .

스토리 보드를 사용하는 대신 프로그래밍 방식으로 뷰를 만드는 것을 선호하는 경우 뷰 컨트롤러의 loadView
메서드를 재정의하면됩니다 . 이 메소드의 구현은 다음을 수행해야합니다.

(…)

3. 자동 레이아웃을 사용 하는 경우 방금 만든 각보기에 충분한 제한을 할당하여보기의 위치와 크기를 제어합니다 . 그렇지 않은 경우 viewWillLayoutSubviews
viewDidLayoutSubviews메서드를 구현 하여 뷰 계층 구조에서 하위 뷰의 프레임을 조정합니다. “View Controller의보기 크기 조정”을 참조하십시오.

업데이트 2 : WWDC 2015 기간 동안 애플은 새로운 설명했다updateConstraintsupdateViewConstraints권장 사용 :

실제로,이 모든 것은 뷰가 다음 레이아웃 패스를 위해 제때에 제약 조건을 변경할 수있는 기회를 제공하는 방법이지만 실제로는 필요하지 않은 경우가 많습니다.

모든 초기 제약 설정은 이상적으로 Interface Builder 내에서 발생해야합니다.

또는 제약 조건을 프로그래밍 방식으로 할당해야하는 경우 viewDidLoad와 같은 위치가 훨씬 좋습니다.

업데이트 제약은 주기적으로 반복해야하는 작업에만 해당됩니다.

또한 그렇게해야 할 필요가있을 때 제약 조건을 변경하는 것은 매우 간단합니다. 반면에 해당 로직을 관련된 다른 코드와 분리하여 나중에 실행되는 별도의 메서드로 이동하면 코드를 따르기가 훨씬 더 어려워 지므로 유지 관리가 더 어려워집니다. , 다른 사람들이 이해하기가 훨씬 더 어려울 것입니다.

그렇다면 언제 업데이트 제약을 사용해야합니까?

음, 그것은 성능으로 귀결됩니다.

제약 조건을 변경하는 것이 너무 느리다면 업데이트 제약 조건이 도움이 될 수 있습니다.

업데이트 제약 조건 내에서 제약 조건을 변경하는 것이 실제로 다른 시간에 제약 조건을 변경하는 것보다 빠릅니다.

그 이유는 엔진이이 패스에서 발생하는 모든 제약 변경 사항을 배치로 처리 할 수 ​​있기 때문입니다.


답변

BOOL을 만들고 -updateConstraintsUIView (또는 -updateViewConstraintsUIViewController의 경우) 에서 설정하는 것이 좋습니다 .

-[UIView updateConstraints]: (애플 문서)

제약 조건 자체를 설정하는 사용자 지정보기는이 메서드를 재정 의하여 수행해야합니다.

뷰의 수명 동안 -updateConstraints및 둘 다 -updateViewConstraints여러 번 호출 될 수 있습니다. ( setNeedsUpdateConstraints예를 들어 뷰를 호출 하면 이것이 발생하도록 트리거됩니다.) 결과적으로 BOOL을 사용하여 특정 제약 조건 설정을 한 번만 수행하거나 확인하여 중복 제약 조건을 만들고 활성화하지 않도록해야합니다. 새 제약 조건을 생성 및 활성화하기 전에 기존 제약 조건을 비활성화 / 제거합니다.

예를 들면 :

  - (void)updateConstraints {  // for view controllers, use -updateViewConstraints

         if (!_hasLoadedConstraints) {
              _hasLoadedConstraints = YES;
             // create your constraints
         }
         [super updateConstraints];
    }

Apple의 문서 super가 마지막 단계로 전화 를 권장한다고 지적한 의견에서 @fresidue를 응원 합니다. super일부 제약 조건을 변경하기 전에 호출 하면 런타임 예외 (크래시)가 발생할 수 있습니다.


답변

이것은 Apple의 WWDC 비디오 및 문서에 따라 ViewDidLoad에서 수행되어야합니다.

사람들이 updateConstraints를 추천하는 이유를 모릅니다. updateConstraints에서 수행하면 뷰가 이미 자동 마스크를 고려했기 때문에 자동 크기 조정으로 NSAutoresizingMaskLayoutConstraint에 문제가 발생합니다. 작동하려면 updateConstraints에서 제거해야합니다.

UpdateConstraints는 ‘업데이트’해야 할 때 초기 설정에서 변경 등을 수행해야합니다.


답변

레이아웃 하위보기 방법을보기에서 수행하십시오.

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()
}


답변

스토리 보드에있는 사람들이로드되기 전에 제약 조건을 변경하는이 솔루션이 있습니다. 이 솔루션은 뷰가로드 된 후 모든 지연을 제거합니다.

-(void)updateViewConstraints{

    dispatch_async(dispatch_get_main_queue(), ^{

            //Modify here your Constraint -> Activate the new constraint and deactivate the old one

            self.yourContraintA.active = true;
            self.yourContraintB.active= false;
            //ecc..
           });

    [super updateViewConstraints]; // This must be the last thing that you do here -> if! ->Crash!
}


답변

viewWillLayoutSubviews 에서도 설정할 수 있습니다 .

 override func viewWillLayoutSubviews() {

    if(!wasViewLoaded){
        wasViewLoaded = true

        //update constraint

        //also maybe add a subview            
    }
}


답변

이것은 나를 위해 일했습니다.

스위프트 4.2

override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)

// Modify your constraints in here

  ...

}

솔직히 그만한 가치가 있는지 확실하지 않지만. viewDidLoad ()보다로드 속도가 약간 느립니다. 엄청나게 커지고 있기 때문에 후자 밖으로 옮기고 싶었습니다.