Categories
Swift 개발(Development)

FetchedRequest.wrappedValue 접근시 crash 문제

하고자 했던 것은 앱이 실행될 때, CoreData 에 데이터가 있는지 체크해서 있으면 그것을 사용하고, 없으면 인터넷에서 데이터를 받아 그것을 CoreData 에 저장하려는 것이었다. 체크를 위해 처음에 작성한 코드는 아래와 같다.

struct ContentView: View {
    let req = FetchRequest<UserModel>(entity: UserModel.entity(), sortDescriptors: [])
    @State private var needToFetch = false

    init() {
        checkData()
    }

    var body: some View {
        ... // use needToFetch variable
    }

    func checkData() {
        if self.req.wrappedValue.count == 0 {
            print("no data")
            self.needToFetch = true
        } else {
            print("there is data")
            self.needToFetch = false
        }
    }
}

그런데 실행해보면 self.req.wrappedValue.count 에 접근하는 순간 EXC_BAD_INSTRUCTION 에러와 함께 crash가 발생한다. checkData 함수 안을 DispatchQueue.main.async 로 감싸보면 crash 가 발생하지 않는데, 이것을 보면 thread 와 관련된 이슈가 있는 것 같다. 대신 async 로 처리하게 되면 @State 가 무력화 되는지 needToFetch 의 값이 바뀌어도 body가 다시 그려지지 않는다.

그래서 해결한 방법이 아래와 같다.

struct ContentView: View {
    let req = FetchRequest<UserModel>(entity: UserModel.entity(), sortDescriptors: [])
    @State private var needToFetch = false

    var body: some View {
        Text("hello world")
            .onApper(perform: req.wrappedValue.count == 0 ? fetchData : useCoreData)
    }
}

init 함수를 통해 fetchRequest.wrappedValue 에 접근하지 않고 onApper modifier 를 통해 분기하니 crash 없이 원하는 결과를 얻을 수 있었다.