SwiftUI holding reference to deleted core data object causing crash

后端 未结 6 740
谎友^
谎友^ 2021-01-31 04:38

Im finding it impossible to use core data with SwiftUI, because as I pass a core data to a view observed object variable, the navigation link view will hold a reference to the o

6条回答
  •  悲&欢浪女
    2021-01-31 04:56

    I basically had the same issue. It seems that SwiftUI loads every view immediately, so the view has been loaded with the Properties of the existing CoreData Object. If you delete it within the View where some data is accessed via @ObservedObject, it will crash.

    My Workaround:

    1. The Delete Action - postponed, but ended via Notification Center
        Button(action: {
          //Send Message that the Item  should be deleted
           NotificationCenter.default.post(name: .didSelectDeleteDItem, object: nil)
    
           //Navigate to a view where the CoreDate Object isn't made available via a property wrapper
            self.presentationMode.wrappedValue.dismiss()
          })
          {Text("Delete Item")}
    
    

    You need to define a Notification.name, like:

    extension Notification.Name {
    
        static var didSelectDeleteItem: Notification.Name {
            return Notification.Name("Delete Item")
        }
    }
    
    1. On the appropriate View, lookout for the Delete Message
    
    // Receive Message that the Disease should be deleted
        .onReceive(NotificationCenter.default.publisher(for: .didSelectDeleteDisease)) {_ in
    
            //1: Dismiss the View (IF It also contains Data from the Item!!)
            self.presentationMode.wrappedValue.dismiss()
    
            //2: Start deleting Disease - AFTER view has been dismissed
            DispatchQueue.main.asyncAfter(deadline: .now() + TimeInterval(1)) {self.dataStorage.deleteDisease(id: self.diseaseDetail.id)}
        }
    
    
    1. Be safe on your Views where some CoreData elements are accessed - Check for isFault!
    
        VStack{
             //Important: Only display text if the disease item is available!!!!
               if !diseaseDetail.isFault {
                      Text (self.diseaseDetail.text)
                } else { EmptyView() }
        }
    
    

    A little bit hacky, but this works for me.

提交回复
热议问题