본문 바로가기

SwiftUI

[SwiftUI] ForEach를 통해 뷰 생성 시 duplicated init 버그

1.  현상

현상은 iOS 16.0 이상에서 List, VStack 등 내부에서 ForEach를 통해 여러 뷰를 생성할 때 실제로는 뷰가 두 번씩 init된다는 것이다.
이렇다보니 뷰 생성 시 수행하는 로직이 있었는데 해당 로직이 불필요하게 2배씩 호출되는 이슈가 있었다. (body에는 한 번만 진입한다)

2. 샘플 코드 및 결과

아래는 간단하게 코드와 해당 코드의 실행 결과이다.

struct ContentView: View {
    
    var numbers: [Int] = Array(1...10)
    
    var body: some View {
        VStack {
            ForEach(self.numbers, id: \.self) { number in
                NumberView(number: number)
            }
        }
        .padding()
    }
}

struct NumberView: View {
    
    var number: Int
    
    init(number: Int) {
        self.number = number
        print("🔴 Init > NumberView \(number)")
    }
    
    var body: some View {
        let _ = print("🔵 Draw > NumberView \(self.number) body")
        Text("NumberView - \(self.number)")
    }
    
}

 

iOS 15.5 iOS 16.1

3. 해결(못함ㅋ)

원인을 발견하지는 못했다. iOS 버전에 따라 달라지는 걸 보니 애플 버그인가 싶기도하고..

 

단, WWDC21 Demystify SwiftUI 영상을 참고해보니 SwiftUI에서 view value의 lifetime을 제어하는 것은 불가능하다는 것을 알 수 있었다. view value는 일시적이므로 여기에 의존해서는 안되고, view identity에 의존해야한다.

 

여기에 더해서, SwiftUI View fundamentals 글에서 "view init 단계에서 뭘 하지 마라" 라고 한다..!

4. 결론

아직은 UIKit가 좋은듯..ㅎ

'SwiftUI' 카테고리의 다른 글

[SwiftUI] UICollectionView + SwiftUI 뷰 혼용해서 사용하기  (1) 2023.08.22