Skip to content

[대황] Demystify SwiftUI performance

Mason Kim edited this page Jul 24, 2024 · 1 revision
  • 업데이트 프로세스

  • stored property -> dynamic property -> view 순서

    • image
  • 디버깅 목적의 프린트 구문 -> 뷰가 다시 그려지는 변화된 이유를 보여줌

    expression Self._printChanges() // LLDB
    let _ = Self._printChanges()    // body 내부
  • 하위 뷰로 구성할 때, 특정 뷰가 사용하는 프로퍼티만 넘기면 최적화할 수 있음

  • 예를 들어 이런 형태의 뷰라면 Dog 의 다른 프로퍼티가 변경되어도 DogImage 가 다시 그려짐

struct DogImage: View {
  var dog: Dog
	
  var body: some View {
    let _ = Self._printChanges()
    dog.image
      .resizable()
  • 실제로 뷰에서 사용하는 Image 만 받도록 변경하면 image 가 변경될 때만 다시 그려짐
struct DogImage: View {
  var image: Image
	
  var body: some View {
    let _ = Self._printChanges()
    image
      .resizable()
  • 작은 뷰에 적합한 테크닉이지만, 너무 큰 구조체에서는 안좋을 수도 있어서 판단을 잘 해야한다.
    • ex) 액션들이 필요한 경우에는 closure 를 다 빼줘야 하므로, 오히려 불편해지는 경험
  • Observable을 사용하면 자동으로 의존성을 설정해줌. -> 필요한 의존성만 스코핑하는 데 유리.
  • @State@StateObject 인 ViewModel / Model 의 init에서 너무 많은 연산을 하지 말 것
    • TCA Reducer 도 동일한듯
  • List + ForEach 는 최적화가 일어남
  • 데이터 최적화를 위해 ID값을 처음에 한 번에 다 모아놓고 처리함
  • 그러므로, ID를 빠르게 만들어야 로딩과 업데이트가 빨라짐
  • List 는 TableView 처럼 눈에 보이는 뷰 + 미리 보여질 뷰 정도만 생성함 image
  • List + ForEach 내부에 if 문을 사용하지 말 것 / AnyView 도 마찬가지로 사용X
    • ForEach 내부에 flat 한 형태로 1depth 로 구성하는 것이 좋음
  • if문을 써야 한다면, 애초에 필터링이 완료된 것을 ForEach 에 넘기는 것이 나음
    • 필터링 로직은 Model 에서 완료하고 body는 보여주게만 처리 -> body가 하는 연산은 뷰 외에 최소화 하는 것이 좋음
  • 중첩 ForEach 는 지양. 허용되는 케이스는 Section -> (회사 코드 구성 동일)
    • Section을 쓰면 List가 이를 보고 최적화를 해줄 수 있음
Clone this wiki locally