Fetch data from CoreData for iOS 14 widget
Asked Answered
K

2

19

I want to display data fetched from Core Data in a widget. But @FetchRequest doesn’t work on widgets.

As I understand, we have to create an app group and make a shared persistent container.

What I want to know is how to read (fetch) data on widgets from that shared persistent container or simply, how to display data fetched from Core Data in widgets.

Kellerman answered 17/9, 2020 at 10:49 Comment(0)
R
34

First you need to create an AppGroup which will be used to create a Core Data Persistent Container (here is a good explanation how to do it)

Then you need to create your own CoreData stack (an example can be found when you create a new empty project with CoreData enabled).

Assuming you have already created your Core Data model (here called DataModel), you now need to set the container url to your custom shared container location:

let containerURL = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: <your_app_group>)!
let storeURL = containerURL.appendingPathComponent("DataModel.sqlite")
let description = NSPersistentStoreDescription(url: storeURL)

let container = NSPersistentContainer(name: "DataModel")
container.persistentStoreDescriptions = [description]
container.loadPersistentStores { ... }

Now you can get the managedObjectContext from your shared Persistent Container:

let moc = CoreDataStack.shared.managedObjectContext

and perform a fetch request with it (more information here)

let predicate = NSPredicate(format: "attribute1 == %@", "test")
let request = NSFetchRequest<SomeItem>(entityName: "SomeItem")
let result = try moc.fetch(request)

Apart from all the links above I recommend you also read this tutorial about Core Data:


Here is a GitHub repository with different Widget examples including the Core Data Widget.

Roslynrosmarin answered 17/9, 2020 at 20:8 Comment(8)
Thanks pawello2222 for this detailed answer. To elaborate on pawello2222's answer, if you use CloudKit, replace NSPersistentContainer with NSPersistentCloudKitContainer (even on the newly created CoreData stack)Kellerman
Hey pawello2222, thanks so much for the answer and for sharing that GitHub repository. I've followed the code in that repository and my widget refreshes completely fine. But I lost all the data on my old managedObjectContext. Can you please tell me how to transfer the data on the old managedObjectContext to the new managedObjectContext in the CoreData stack?Deterge
@Deterge This is because you create a new NSPersistentContainer which is located in a different place than your old one. You need to move/copy your old container to the new location. This post might help you: iOS 11+ How to migrate existing Core Data to Shared App Group for use in extension?Roslynrosmarin
Does this also work with custom Core Data classes?Dixil
@Dixil This doesn't change any Core Data behaviour, just the container location. Everything else is like in any standard app.Roslynrosmarin
So, if i have some Core Data custom classes with custom methods etc. i need them to target my widget or not?Dixil
@Dixil You need to make sure that all what is needed in the widget is added to the widget target. If you plan to use Core Data and custom classes in the widget, you need to add them all to the widget target.Roslynrosmarin
I followed the same steps above but the app crashed, if anyone can help the issue link: #73820733Wapentake
T
3

For people who did all the work above, and finally can get the connection to your Core Data (e.g. you can get the count of request), but can't fetch the request, is mostly because that the entity you're fetching contains transformable type, and for some reason this error occurred: Cannot decode object of class, try fix this.

Tamarra answered 12/10, 2022 at 5:50 Comment(2)
If you have a new question, please ask it by clicking the Ask Question button. Include a link to this question if it helps provide context. - From ReviewAzobenzene
They dont have a new question, they just gave additional information that may help someone for whom the accepted answer did not work. Please go be pedantic somewhere else.Veinule

© 2022 - 2024 — McMap. All rights reserved.