본문 바로가기
SwiftUI

SwiftUI) Preview 크래시 발생 사례 (EnvironmentObject)

by 김 Duke 2024. 1. 17.

목차

    스유를 사용하다보면 Preview에서 크래시가 종종 일어난다. 

    사실 이전에 Preview 크래시 관련 글을 작성했었는데, 그땐 일반적인 문제보다 특수 경우였고 xcode 버그로 판명났다.

    근데 그 글이 구글에 Preview 크래시 관련해서 검색하면 제일 상단에 떠서 사람들 유입이 계속 있었다. 

    그래서 개발하던 도중 많이 봐왔던 사례에 관해 글을 쓰려고 한다.

     

    일반적으로 코드에 문제가 있는 경우 xcode 자체에서 오류를 발생시켜서 개발자가 인지하게 해준다.

    하지만 Preview 크래시의 경우 xcode가 안잡아주는 경우가 있고 그래서 뭐가 문젠지 모를 때가 많다.

     

    글 이해에 도움을 줌

    - 사례를 순서대로 읽으시는 것을 권장

    - 코드를 긁어다가 주석을 해제해서 비교하기

     


     

    Data binding, EnvironmentObject 관련 사례

    오늘 다룰 주제는 Data binding 관련 EnvironmentObject를 사용할 경우이다.

    EnvironmentObject는 뷰에 선언만 하고 값을 할당하지 않는다. 그렇기 때문에 값을 할당해줘야한다.

    일반적으로 StateObject로 객체를 선언하고 값을 할당한다. 하지만 이 글에서는 단순하게 작성하여 이해를 돕기 위해 ViewModel을 직접 초기화해서 전달했다.

     

    아래에서 사용할 ViewModel 코드이다.

    final class ViewModel: ObservableObject {
        @Published var something: String = "Hello, World"
    }

     

     

     

    case 1 DetailView에서의 앱 크래시

    environmentObject를 직접 사용하는 뷰(DetailView)의 프리뷰에 값을 할당하지 않으면 크래시 발생

     

    struct DetailView: View {
        @EnvironmentObject var vm: ViewModel
        var body: some View {
            Text(vm.something)
        }
    }
    
    #Preview {
        DetailView()
    //        .environmentObject(ViewModel())
    }

     

     

     

     

    case 2 SuperView에서 DetailView에 접근할 경우

    SuperView)에서 DetailView(environmentObject를 사용하는 뷰)  값을 할당(주입)해주지 않았을 경우 크래시 발생

    struct SuperView: View {
        var body: some View {
            NavigationStack {
                VStack {
                    NavigationLink {
                        DetailView()
    //                        .environmentObject(ViewModel())
                    } label: {
                        Text("DetailView")
                    }
                }
            }
        }
    }
    
    #Preview {
        SuperView()
    }

     

     

     

     

    case 3 environmentObject의 값을 App 수준에서 할당해줄 때 상위뷰에서 크래시가 나는 경우

    @main
    struct PreviewCrashTestApp: App {
        var body: some Scene {
            WindowGroup {
                SuperView()
                    .environmentObject(ViewModel())
            }
        }
    }
    struct SuperView: View {
        var body: some View {
            NavigationStack {
                VStack {
                    NavigationLink {
                        DetailView()
                    } label: {
                        Text("DetailView")
                    }
                }
            }
        }
    }
    
    #Preview {
        SuperView()
    //        .environmentObject(ViewModel())
    }

     

     

     

     

    case 번외

    case3에서 App 수준에 environmentObject 값을 할당하지 않으면 시뮬레이터가 크래시난다

     

     


    TOP

    Designed by 티스토리