iOS 14 WidgetKit + Core Data/CloudKit

I am trying to build a widget for iOS 14 using WidgetKit and CoreData/CloudKit instance on a new Xcode 12 project.
  1. I have added my CoreData's File Target Membership to both my app and widget

  2. I have added an App Group to my main App Target.

  3. My Persistence.swift looks like this:

Code Block
init(inMemory: Bool = false) {
    container = NSPersistentCloudKitContainer(name: "test-cd")
    let storeURL = URL.storeURL(for: "group.test-data", databaseName: "test-cd")
    let storeDescription = NSPersistentStoreDescription(url: storeURL)
    container.persistentStoreDescriptions = [storeDescription]


4. My widget looks like this:
Code Block
struct Provider: TimelineProvider {
  var managedObjectContext : NSManagedObjectContext
   
  init(context : NSManagedObjectContext) {
    self.managedObjectContext = context
  }
...
}



Code Block
@main
struct test_widget: Widget {
  let kind: String = "test_widget"
   
  var persistentContainer = PersistenceController.shared.container
  var body: some WidgetConfiguration {
    StaticConfiguration(kind: kind, provider: Provider(context: persistentContainer.viewContext)) { entry in
      test_widgetEntryView(entry: entry)
    }
    .configurationDisplayName("My Widget")
    .description("This is an example widget.")
  }
}

5. And my widget's entry view looks like this:
Code Block
struct test_widgetEntryView : View {
  @FetchRequest(
    sortDescriptors: [NSSortDescriptor(keyPath: \Item.checked, ascending: true)],
    animation: .default)
  private var items: FetchedResults<Item>
   
  var entry: Provider.Entry
  var body: some View {
    LazyVStack {
      ForEach(items) { item in
        HStack {
Text("\(item.name)")
}
      }
    }
    .padding(.horizontal)
  }
}


But the app crashes on ForEach(items) as soon as it is launched:


Thread 1: EXCBADINSTRUCTION (code=EXCI386INVOP, subcode=0x0)

Any suggestions as to what is going wrong here?







Accepted Reply

Hi!

Widget views are created up front and stored by the system to be rendered out of the widget's process. So @FetchRequest won't be able to work on these views.

The recommended way is to do the fetch in your TimelineProvider's methods and have Item as a property on TimelineEntry.

Replies

Hi!

Widget views are created up front and stored by the system to be rendered out of the widget's process. So @FetchRequest won't be able to work on these views.

The recommended way is to do the fetch in your TimelineProvider's methods and have Item as a property on TimelineEntry.