View Drawing Cycle
view가 로드 또는 변경이 있을 때, 화면에 그려지는 사이클을 말한다.
⭐ 아래 순서로 drawing이 일어난다
(Constraints -> Layout -> Draw)
Constraints: 오토레이아웃 업데이트 (제약을 업데이트)
Layout: 하위뷰의 레이아웃으로 위치&크기 (재)조정
Draw: 실제 내부 컨텐츠 (다시) 그리기
⭐1초에 60번씩 아래 메서드(함수)들이 자동 호출 된다.
- updateConstraints (오토레이아웃이 업데이트 과정)
현재 기기의 화면 크기를 기준으로 제약을 업데이트하는 과정이다.
동적인 오토레이아웃 변경이 일어날 경우 제약조건을 변경한다.
✅ 제약을 함수로 업데이트하고, 여러 개의 제약을 한 번에 업데이트 하는 상황이 아니라면 잘 사용하지 않는다.
// 테이블 뷰 셀 같은 컴포넌트 요소를 코드로 구성할 때 활용할 수 있다.
// updateConstraints에서 레이아웃 제약이 확정된다.
override func updateConstraints() {
setConstraints() // 오토레이아웃을 설정하는 함수
super.updateConstraints()
}
//반드시 super.updateConstraint()를 오토레이아웃 설정 후에 호출해야한다. 출처 - document
직접 호출이 아닌 updateConstraints를 호출할 수 있도록 예약하는 형태의 메서드가 존재한다.
setNeedsUpdateConstraints() -> 다음 사이클에 오토레이아웃 조정 요청
updateConstraintsIfNedded() -> 1/60초 (0.016초) 생략하고, 바로 오토레이아웃 조정 요청
- layoutSubviews (하위 뷰들의 위치/크기를 계산하고 배치하는 과정)
frame 기준으로 알 수 있는 시점, 하위 뷰들의 frame 등 직접 설정 가능
View들의 레이아웃 프레임이 정해지는 시기이다.
해당 메서드를 호출하면 해당 View의 모든 subView들이 layoutSubViews()를 연달아 호출한다.
✅ 소모되는 비용이 너무 크기 때문에 직접 호출은 하지 않는다.
// 테이블 뷰 셀 같은 컴포넌트 요소를 코드로 구성할 때 활용할 수 있다.
// 오토레이아웃(제약)으로 인해 뷰들의 frame(크기)가 정해지는 시점이기 때문에 정해진 크기로 인한 작업들을 할 수 있다.
override func layoutSubviews() {
super.layoutSubviews()
self.mainImageView.clipsToBounds = true
self.mainImageView.layer.cornerRadius = self.mainImageView.frame.width / 2
}
layoutSubView를 호출할 수 있도록 예약하는 형태의 메서드가 존재한다.
setNeedsLayout() -> 다음 사이클에서 위치/크기 조정 요청
layoutIfNeeded() -> 1/60초 (0.016초) 생략하고, 바로 위치/크기 조정 요청
- draw
실제로 화면을 그리는 또는 다시 그리는 과정
⭐⭐⭐ 애플은 updateConstraints, layoutSubviews, draw는 Update Cycle에서 수행되는게 더 바람직 하므로 직접 호출하지 말라고한다. ⭐⭐⭐
⭐️ layoutIfNedded() 이런 함수는 애니메이션 효과를 줄 때 사용한다.
myViewHeightAnchor, myViewWidthAnchor 값의 변화를 애니메이션 효과를 주는데,
layoutIfNeeded() 메서드를 통해 layoutSubViews() 메서드를 호출한다.
아래의 조건문 참과 거짓에 따라 오토레이아웃 값이 결정된다.
결정된 오토레이아웃을 통해 배치를 진행해야 하는데,
이를 layoutIfNeeded() 메서드를 통해 layoutSubViews()를 자동 호출하여
2초 동안 자동 배치를 요청하는 것이다.
@objc func buttonAnimationEffect(){
print(#function)
if !myView.onAndOff {
myViewHeightAnchor.constant = 250
myViewWidthAnchor.constant = 150
} else {
myViewHeightAnchor.constant = 80
myViewWidthAnchor.constant = 100
}
UIView.animate(withDuration: 2) {
self.view.layoutIfNeeded()
} completion: { success in
print("애니메이션 처리 완료")
}
myView.toggle()
}
⭐️ 오토레이아웃 또는 프레임 기준 제약 조건을 줄 때는?
오토레이아웃 → updateConstraints()
프레임 → layoutSubViews()
// 버튼의 넓이와 높이를 오토레이아웃으로 맞춘다면
override func updateConstraints() {
print(#function)
myButton.widthAnchor.constraint(equalTo: self.widthAnchor, multiplier: 0.5).isActive = true
myButton.heightAnchor.constraint(equalTo: self.heightAnchor, multiplier: 0.5).isActive = true
myButton.centerXAnchor.constraint(equalTo: self.centerXAnchor).isActive = true
myButton.centerYAnchor.constraint(equalTo: self.centerYAnchor).isActive = true
super.updateConstraints()
}
// 버튼의 넓이와 높이를 프레임기준으로 맞춘다면
override func layoutSubviews() {
super.layoutSubviews()
print(#function)
myButton.frame.size = CGSize(width: self.frame.size.width/2, height: self.frame.size.height/2)
myButton.center = CGPoint(x: self.bounds.midX, y: self.bounds.midY)
}
'UIKit > 기본' 카테고리의 다른 글
Filemanager로 CRUD 해보기 (1) | 2024.04.04 |
---|---|
네비게이션 바 + 탭 바 적용 (0) | 2024.03.29 |
앱의 생명주기 (App Life Cycle) (0) | 2024.03.27 |
ViewController의 life cycle (1) | 2024.03.27 |
컴플리션 핸들러 - 비동기 처리 (함수가 끝난 후 결과 알려줄 때) (0) | 2024.03.19 |