Crash when using shared instance of a data controller in App Entity definition

131 views Asked by At

I'm getting an unusual unrecognized selector sent to instance crash when trying to access a shared data controller object from inside an app shortcuts AppEntity definition. It seems to relate to [NSCFString bytes].

The data controller is declared in my main app and passed through the environment:

struct myApp: App {
    
    @StateObject var dataController: DataController
 
    var body: some Scene {
        WindowGroup {
            ContentView()
                .environmentObject(dataController)
        }
    }

    init() {
        _dataController = StateObject(wrappedValue: DataController.shared)
}

In my app entity and widgets, it is accessed as the shared instance. For example, here is an abridged version of the app entity and query.

struct MyAppEntity: AppEntity {
    
    @Property(title: "Name")
    var name: String?

    // ... some code omitted
    
    struct MyAppEntityQuery: EntityQuery {
        
        // Option 1: Having data controller here flags a warning about it
        // not being a Sendable type
        let dataController = DataController.shared
        
        func entities(for identifiers: [MyAppEntity.ID]) async throws -> [MyAppEntity] {
            // Option 2: Having data controller here in the function is
            // transient, so no Sendable warning as above
            let dataController = DataController.shared
            let items = dataController.getAllItems()

            // ... use items to provide list for disambiguation
        }
        
        // ... some code omitted
    }
}

Note the two options for location of the data controller. Both cause crashes, and using it as a top-level property raises a warning that it is not Sendable like the rest of the struct.

The problem is that the dataController.getAllItems() method causes the crash when it in turn calls viewContext.fetch(Item.fetchRequest().


Behind the scenes, the getAllItems() method does a Core Data fetch to return the items. The crash seems to happen (intermittently) if deleting or adding items, and sometimes on app startup (iOS seems to instantiate app entities at startup, so this code gets called). Interestingly, using the actual app shortcut works fine!

I had tried with the SwiftUI @FetchRequest wrappers, like I use in the main app, but there is no managed object context in the environment here.

I wonder if the Core Data stack is not ready in the shared instance when the App Entity code runs? Any advice would be appreciated.


One solution I'm considering is to save a lightweight representation of the data from Core Data as JSON and look this up to get the items for disambiguation. This is what I do for widgets as they are in an extension. I previously used an intent extension but this is iOS16 app shortcuts which (AFAIK) run in the main app process.


Edit

I was able to work around this by avoiding calling core data, and instead using the JSON-encoded data in the app group container that I already use for widgets. However that does not explain the issue here.

0

There are 0 answers