iyOmSd/Title: Swift

[Swift] View Life Cycle UI업데이트 관련 함수

냄수 2020. 10. 16. 15:57
반응형

UI가 업데이트되는 주기를 알아볼 거예요

 

일반적으로 뷰가 생성될 때 알고 있는 주기는

loadView

viewDidLoad

viewWillAppear

viewDidAppear

많이 들어 봤을 거예요

 

여기서 더 자세하게 살펴볼 거예요

저 사이에는 숨겨진 동작들이 있어요

 

파란 배경 - 오버라이드 가능

빨간 배경 - 오버라이드 불가(뷰 컨트롤러 기준 오버라이드 불가)

 

 

loadView

viewDidLoad

viewWillAppear

 

ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ Constraints ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ

updateConstraints

intrinsicContentSize

updateViewConstraints

 

ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ Layout ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ

viewWillLayoutSubviews

layoutSubviews

viewDidLayoutSubviews

 

ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ Draw ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ

drawRect

 

viewDidAppear

 

 

 

 

레이아웃 변경을 적용시키기 위해서는

setNeedsLayout과 layoutIfNeeded를 사용할 수 있어요

 

 

둘의 차이는 다음 업데이트 사이클을 기다리는 함수와

당장 업데이트할 수 있는 함수의 차이가 있고요

 

setNeedsLayout 같은 경우에는

다음 업데이트 사이클을 기다린 뒤 업데이트를 시켜줘요

레이아웃 업데이트를 한 번에 통합해서 업데이트할 수 있어서 일반적으로 성능이 좋다고 하네요

바뀌는 UI가 많던가

바로 볼 필요가 없는 급한 UI가아니라면 쓰는 게 좋겠네요

 

또한 호출하면

viewWillLayoutSubviews와 viewDidLayoutSubviews도 호출되구요

하위 뷰가 추가되거나 layer속성을 변경하거나 애니메이션이 추가되거나 등

기본적으로 시스템이 호출시키는 경우도 있어요

 

뷰컨 생성시 처음에 불리는 viewWillLayoutSubviews은

Contraints과정을 지난 후이기 때문에 위치는 잡혀있어요

viewWillAppear보다 뒤에서 호출되는 함수이기 때문에 레이아웃 처리 작업을 할 수 있어요

viewDidLayoutSubviews에서는 스토리보드상의 레이아웃이 아니라 폰에 적용된 크기로

컴포넌트의 크기를 받아올 수 있어서

레이아웃 크기에 관련한 작업을 할 때 편해요!

setNeedsLayout을 통해서 불리는 처리도 해줄 수 있겠죠?

 

 

 

간단한 예시로

class MyViewController : UIViewController {
    var label: UILabel!
    var color: UIColor = .black {
        didSet {
            view.setNeedsLayout()
        }
    }
    
    ...
    
    override func viewWillLayoutSubviews() {
        label?.textColor = color
    }
     
    ...
    
    func clickButton() {
        color = .blue
    }
}
    

코드를 보면

버튼을 클릭하면 색 변수가 파란색이 되고

그때 setNeedsLayout을 통해서

뷰의 UI를 업데이트할 수 있는 방식이죠

 

 

layoutIfNeeded 같은 경우에는

즉시 업데이트를 시키고

레이아웃 관련 콜백을 호출하지 않고 종료돼요

viewWillLayoutSubviews 와같은 함수들을 호출하지 않는 거예요

바로바로 변화를 보고 싶은 경우 쓰면 좋을 것 같네요

특히 애니메이션 같은 경우 0.1초도 중요하잖아요? 그럴 때 사용하면 바로바로 볼 수 있겠죠

setNeedsLayout은 주기를 기다렸다가 일어나기 때문에 원하는 애니메이션을 볼 수 없을 수도 있어요

 

 

간단한 예시로

viewLayout.constant = 0
UIView.animate(withDuration: 0.3) { 
    view.layoutIfNeeded()
}

레이아웃을 수정하고

layoutIfNeeded를 애니메이션함수 안에 넣어두면 잘 동작하는걸 볼 수 있죠

 

반응형