iOS에서 뷰는 데이터 변화 및 사용자 입력에 따라 동적으로 업데이트 되어야 합니다. iOS에서는 이 과정을 어떻게 처리하는지 알아보도록 하겠습니다.
-
업데이트 사이클
뷰는 여러가지 이유로 업데이트 되어야 합니다. 사용자의 터치 입력, 연관된 센서값의 변화, 데이터의 변화 등 여러가지 이유로 뷰는 변화할 수 있습니다. 이러한 변화는 여러군데에서 산발적으로 일어나며 시간적으로도 얼마든지 겹칠 수 있습니다. 따라서 매 변화마다 뷰를 업데이트하는 것보다는 한꺼번에 처리하는 것이 성능적으로 좋을 것입니다. iOS는 UIKit을 사용하고, UIKit은 이벤트를 모아서 처리하기 위해 다음과 같은 과정을 거칩니다.-
이벤트가 발생합니다. 이 이벤트는 터치 이벤트일 수도 있고, 그 외에 다른 이벤트일 수도 있습니다.
-
UIKit이 responder chain을 타고 이벤트를 적절한 뷰에 전달합니다.
-
해당 뷰는 이벤트를 처리합니다. 이때 다음과 같은 일들이 발생하면 갱신이 필요해집니다.
- 뷰 혹은 서브뷰가 그려지는데 필요한 프로퍼티들(frame, bounds,alpha 값 등)이 변경됩니다.
- setNeedsLayout가 호출됩니다. 이 함수는 레이아웃을 무효화시켜 레이아웃을 다시 조정하도록 유도합니다.
- setNeedsDisplay, setNeedsDisplay(_:) 메소드가 호출됩니다. 이 메소드는 뷰 자체를 다시 그리도록 합니다.
- 뷰에 연결된 컨트롤러의 데이터가 변경되어 이를 반영해야 됩니다.
-
이벤트 처리가 끝나면, 뷰의 업데이트 사이클이 시작됩니다. 이때 레아아웃 변화를 우선적으로 처리합니다. Autoresizing이 활성화 되어 있다면 AutoResizing에 따라 뷰를 조정하고, 그렇지 않은 경우 layoutSubView를 호출합니다. 이 함수를 호출할 때 오토레이아웃 계산이 일어납니다. 만약 여기서 뷰를 다시 그려야한다고 판단이 된다면 setNeedsDisplay 메소드를 호출할 수 있습니다.
-
다시 그려야 될 뷰가 있다면 다시 그리는 드로잉 사이클이 시작됩니다. 만약 커스텀 뷰에서 draw(_:)를 재정의했다면 draw가 호출됩니다. 이 draw 메소드는 뷰를 다시 그리는데에만 사용되어야 하며, 여기서 레이아웃을 조정하거나 데이터를 조작하면 안됩니다. 시스템 뷰는 draw메소드를 사용하지 않지만 역시 이 단계에서 뷰를 다시 그립니다.
-
업데이트 된 부분과 업데이트 되지 않은 뷰를 합쳐서 그래픽 하드웨어로 보냅니다.
-
그래픽 하드웨어는 이를 렌더링해서 화면에 그립니다.
이렇게 업데이트 사이클이 끝납니다.
-
-
업데이트 사이클 수동으로 실행하기
setNeeds~ 함수는 업데이트가 필요하다고만 체크한 뒤, 바로 업데이트는 하지 않습니다. 업데이트 시점은 시스템이 결정합니다. 만약 이러한 사이클을 강제로 시작하고 싶다면, ~IfNeeded 계열의 함수를 호출할 수 있습니다. layoutIfNeeded, displayIfNeeded가 이에 해당합니다. 이 메소드들은 즉각적으로 사이클을 실행하지만, 뷰 변화량이 많아서 자주 사이클이 실행된다면 성능적인 문제를 야기할 수 있습니다. 따라서 주의해서 써야만 합니다.