관리 메뉴

김종권의 iOS 앱 개발 알아가기

[iOS - swift] layoutIfNeeded() 이해하고 사용하기 (layoutSubviews , Update Cycle, Main Run Loop) 본문

iOS 기본 (swift)

[iOS - swift] layoutIfNeeded() 이해하고 사용하기 (layoutSubviews , Update Cycle, Main Run Loop)

jake-kim 2022. 5. 30. 19:20

Layout 용어와 layoutSubviews() 메소드

  • UIView의 layout이라는 의미는 위치와 크기를 의미
  • layoutSubviews() 메소드는 UIView의 layout을 변경
    • 즉, layoutSubviews() 메소드는 UIView의 위치와 크기를 재조정하는 메소드
  • layoutSubviews()는 재귀적으로 자식들의 layoutSubviews()도 재귀적으로 실행
  • layoutSubviews()가 실행되는 시점은 main run loop에 따라서 실행
    • UI를 건드리는 작업은 디바이스에 부담이 되는 작업이므로 내부적으로 UI 작업에 main run loop라는 방법을 통해 해결

Main Run Loop 개념

  • 앱이 실행되면 iOS는 내부적으로 메인 스레드에서 main run loop를 실행
  • iOS는 UI를 업데이트할때 업데이트하는 일정의 시간을 두어서, UI 렌더링은 값비싼 작업이기에 효율적으로 업데이트하기 위해 Main Run Loop를 만든 것
  • 두 가지 상태로 구성 
    • 사용자의 터치 이벤트나 뷰의 레이아웃을 인식하는 Main Run Loop와 뷰들의 layout을 constraint하는 구조로 존재
    • 뷰의 레이아웃을 변경하는 부분이 값이 많이 들고 중요한 부분이므로 대다수를 차지하고 단순히 사이클을 변경하는 부분은 짧게 존재
    • iOS는 초당 60프레임을 보여주고, Update cycle은 1/60초가 걸림

layoutIfNeeded()

  • layoutIfNeeded()가 호출되면, UI를 업데이트 하라는 queue에 뒷쪽에 넣는것이 아니라, 맨 앞쪽에 넣어서 곧바로 UI가 변경되기를 기대할수있는 메소드
  • 해당 메소드가 호출되면 Update Cycle을 바로 실행하여 레이아웃이 즉각적으로 적용
  • layoutSubviews()는 내부 알고리즘에 의해 최적화되어 있기때문에 명시적으로 불리면 안되므로 애플에서는 layoutIfNeeds() 코드를 통해 layoutSubviews() 메소드가 간접적으로 빠르게 불리도록 설계

ex) 팝업이 아래에서 위로 올라오는 애니메이션 구현

- autolayout으로 아래에서 위로 올라오는 animations을 구현하고 싶을때 UIView.animate의 애니메이션 블럭에 layoutIfNeeded()를 사용

밑에서 위로 올라오는 애니메이션

* 구체적인 코드는 해당 포스팅 글 참고

// 2.0초동안 layoutIfNeeded() 메소드를 실행시킨다는 의미 -> Main Run Loop에서 2.0초동안 레이아웃을 업데이트

@objc private func damping() {
  self.dampingAnimationButton.snp.remakeConstraints {
    $0.center.equalToSuperview()
  }
  UIView.animate(
    withDuration: 2.0,
    delay: 0,
    usingSpringWithDamping: 0.1,
    initialSpringVelocity: 0.9,
    options: [],
    animations: { self.view.layoutIfNeeded() },
    completion: nil
  )
}

 

* 참고

https://developer.apple.com/library/archive/documentation/General/Conceptual/Devpedia-CocoaApp/MainEventLoop.html

Comments