iOS에서 뷰는 데이터 변화 및 사용자 입력에 따라 동적으로 업데이트 되어야 합니다. iOS에서는 이 과정을 어떻게 처리하는지 알아보도록 하겠습니다.

  • 업데이트 사이클
    뷰는 여러가지 이유로 업데이트 되어야 합니다. 사용자의 터치 입력, 연관된 센서값의 변화, 데이터의 변화 등 여러가지 이유로 뷰는 변화할 수 있습니다. 이러한 변화는 여러군데에서 산발적으로 일어나며 시간적으로도 얼마든지 겹칠 수 있습니다. 따라서 매 변화마다 뷰를 업데이트하는 것보다는 한꺼번에 처리하는 것이 성능적으로 좋을 것입니다. iOS는 UIKit을 사용하고, UIKit은 이벤트를 모아서 처리하기 위해 다음과 같은 과정을 거칩니다.

    1. 이벤트가 발생합니다. 이 이벤트는 터치 이벤트일 수도 있고, 그 외에 다른 이벤트일 수도 있습니다.

    2. UIKit이 responder chain을 타고 이벤트를 적절한 뷰에 전달합니다.

    3. 해당 뷰는 이벤트를 처리합니다. 이때 다음과 같은 일들이 발생하면 갱신이 필요해집니다.

      • 뷰 혹은 서브뷰가 그려지는데 필요한 프로퍼티들(frame, bounds,alpha 값 등)이 변경됩니다.
      • setNeedsLayout가 호출됩니다. 이 함수는 레이아웃을 무효화시켜 레이아웃을 다시 조정하도록 유도합니다.
      • setNeedsDisplay, setNeedsDisplay(_:) 메소드가 호출됩니다. 이 메소드는 뷰 자체를 다시 그리도록 합니다.
      • 뷰에 연결된 컨트롤러의 데이터가 변경되어 이를 반영해야 됩니다.
    4. 이벤트 처리가 끝나면, 뷰의 업데이트 사이클이 시작됩니다. 이때 레아아웃 변화를 우선적으로 처리합니다. Autoresizing이 활성화 되어 있다면 AutoResizing에 따라 뷰를 조정하고, 그렇지 않은 경우 layoutSubView를 호출합니다. 이 함수를 호출할 때 오토레이아웃 계산이 일어납니다. 만약 여기서 뷰를 다시 그려야한다고 판단이 된다면 setNeedsDisplay 메소드를 호출할 수 있습니다.

    5. 다시 그려야 될 뷰가 있다면 다시 그리는 드로잉 사이클이 시작됩니다. 만약 커스텀 뷰에서 draw(_:)를 재정의했다면 draw가 호출됩니다. 이 draw 메소드는 뷰를 다시 그리는데에만 사용되어야 하며, 여기서 레이아웃을 조정하거나 데이터를 조작하면 안됩니다. 시스템 뷰는 draw메소드를 사용하지 않지만 역시 이 단계에서 뷰를 다시 그립니다.

    6. 업데이트 된 부분과 업데이트 되지 않은 뷰를 합쳐서 그래픽 하드웨어로 보냅니다.

    7. 그래픽 하드웨어는 이를 렌더링해서 화면에 그립니다.

    이렇게 업데이트 사이클이 끝납니다.

  • 업데이트 사이클 수동으로 실행하기
    setNeeds~ 함수는 업데이트가 필요하다고만 체크한 뒤, 바로 업데이트는 하지 않습니다. 업데이트 시점은 시스템이 결정합니다. 만약 이러한 사이클을 강제로 시작하고 싶다면, ~IfNeeded 계열의 함수를 호출할 수 있습니다. layoutIfNeeded, displayIfNeeded가 이에 해당합니다. 이 메소드들은 즉각적으로 사이클을 실행하지만, 뷰 변화량이 많아서 자주 사이클이 실행된다면 성능적인 문제를 야기할 수 있습니다. 따라서 주의해서 써야만 합니다.


참고 자료 View Programming Guide for iOS