[ios] 레이아웃 제약은 언제 활성화 / 비활성화 할 수 있습니까?

IB에 여러 제약 조건 세트를 설정했으며 일부 상태에 따라 프로그래밍 방식으로 전환하고 싶습니다. 거기의 constraintsAIB에서 설치로 표시된 모두 출구 컬렉션, 그리고 constraintsB모든 출구 수집은 IB에서 제거됩니다.

다음과 같이 프로그래밍 방식으로 두 세트간에 전환 할 수 있습니다.

NSLayoutConstraint.deactivateConstraints(constraintsA)
NSLayoutConstraint.activateConstraints(constraintsB)

근데 … 언제 해야할지 모르겠어요 . 에서 한 번 할 수 있어야 할 것 같지만 viewDidLoad작동하지 않습니다. 나는 전화 해봤 view.updateConstraints()view.layoutSubviews()제약 조건을 설정 한 후,하지만 소용.

viewDidLayoutSubviews모든 제약 조건을 설정하면 예상대로 작동 한다는 것을 알았습니다 . 두 가지를 알고 싶은 것 같아요 …

  1. 이 동작이 발생하는 이유는 무엇입니까?
  2. viewDidLoad에서 제약 조건을 활성화 / 비활성화 할 수 있습니까?


답변

에서 활성화 및 비활성화 NSLayoutConstraints했는데 viewDidLoad아무런 문제가 없습니다. 그래서 작동합니다. 앱과 내 앱 사이에 설정에 차이가 있어야합니다. 🙂

내 설정에 대해 설명하겠습니다. 아마도 당신에게 리드를 줄 수 있습니다.

  1. @IBOutlets활성화 / 비활성화하는 데 필요한 모든 제약 조건을 설정했습니다 .
  2. 에서는 ViewController약하지 않은 클래스 속성에 제약 조건을 저장합니다. 그 이유는 제약 조건을 비활성화 한 후 다시 활성화 할 수 없다는 것을 발견했기 때문입니다. 따라서 비활성화되면 삭제되는 것 같습니다.
  3. 나는 NSLayoutConstraint.deactivate/activate당신처럼 사용하지 않고 대신 constraint.active = YES/를 NO사용합니다.
  4. 제약 조건을 설정 한 후 view.layoutIfNeeded().

답변

어쩌면 당신은 할 수 귀하의 확인 @properties, 교체 weak와 함께strong .

때로는 active = NOset 때문에 다시 self.yourConstraint = nil사용할 수 없습니다 self.yourConstraint.


답변

override func viewDidLayoutSubviews() {
// do it here, after constraints have been materialized
}


답변

나는 당신이 겪고있는 문제는 AFTER viewDidLoad()가 호출 될 때까지 그들의 뷰에 추가되지 않는 제약 때문이라고 생각합니다 . 다음과 같은 여러 옵션이 있습니다.

A) 레이아웃 제약 조건을 IBOutlet에 연결하고 이러한 참조를 통해 코드에서 액세스 할 수 있습니다. 콘센트는 viewDidLoad()킥오프 전에 연결되어 있으므로 제약 조건에 액세스 할 수 있어야하며 계속해서 활성화 및 비활성화 할 수 있습니다.

B)constraints() 다양한 제약 조건에 액세스 하기 위해 UIView의 기능을 사용하려면 viewDidLayoutSubviews()시작 하기 를 기다려야 합니다. 그것이 설치된 제약 조건이있는 펜촉에서 뷰 컨트롤러를 만든 후 첫 번째 지점이기 때문입니다. layoutIfNeeded()완료되면 전화하는 것을 잊지 마십시오 . 이것은 적용 할 변경 사항이있는 경우 레이아웃 패스가 두 번 수행된다는 단점이 있으며 무한 루프가 트리거 될 가능성이 없는지 확인해야합니다.

간단한 경고 : 비활성화 된 제약 조건은 메서드에 의해 반환되지 않습니다 constraints() ! 즉, 나중에 다시 켜려는 의도로 제약 조건을 비활성화하면 해당 참조를 유지해야합니다.

C) 스토리 보드 접근 방식을 잊어 버리고 대신 수동으로 제약 조건을 추가 할 수 있습니다. 이 작업을 수행하고 viewDidLoad()있으므로 즉시 레이아웃을 변경하는 대신 객체의 전체 수명 동안 한 번만 수행하는 것으로 가정하므로 허용되는 방법이어야합니다.


답변

priority속성을 “활성화”및 “비활성화”하도록 조정할 수도 있습니다 (예 : 활성화하려면 750 값, 비활성화하려면 250). 어떤 이유로 activeBOOL을 변경해도 UI에 영향을 미치지 않았습니다. 필요 layoutIfNeeded하지 않으며 viewDidLoad 또는 그 이후에 언제든지 설정 및 변경할 수 있습니다.


답변

사용하지 않는 제약 조건을 비활성화하는 적절한 시간 :

-(void)viewWillLayoutSubviews{
    [super viewWillLayoutSubviews];

    self.myLittleConstraint.active = NO;
}

명심 viewWillLayoutSubviews좋아, 무거운 계산하므로, 여러 번 호출 할 수 있을까?

참고 : 나중에 제약 조건 중 일부를 다시 적용하려면 항상 strong참조를 저장 하십시오.


답변

뷰가 생성 될 때 다음 라이프 사이클 메소드가 순서대로 호출됩니다.

  1. loadView
  2. viewDidLoad
  3. viewWillAppear
  4. viewWillLayoutSubviews
  5. viewDidLayoutSubviews
  6. viewDidAppear

이제 귀하의 질문에.

  1. 이 동작이 발생하는 이유는 무엇입니까?

답변 : 뷰의 뷰에 대한 제약을 설정하려고 할 때 viewDidLoad뷰의 경계가 없으므로 제약을 설정할 수 없기 때문입니다. viewDidLayoutSubviews뷰의 경계가 확정 된 후에야 합니다.

  1. viewDidLoad에서 제약 조건을 활성화 / 비활성화 할 수 있습니까?

답변 : 아니요. 위에 설명 된 이유.