Share data between main App and Widget in SwiftUI for iOS 14

Viewed 11194
@main
struct ClockWidgetExt: Widget {
    private let kind: String = "ClockWidgetExt"
    
    public var body: some WidgetConfiguration {
        StaticConfiguration(kind: kind, provider: Provider(), placeholder: PlaceholderView()) { entry in
            HomeTestView()
        }
        .configurationDisplayName("My Widget")
        .description("This is an example widget.")
    }
}

How can I get data from my Main App to the widget?

2 Answers

You can add the AppGroup capability for both your Widget and App (here is a very good explanation how to add it).


UserDefaults

Instead of

UserDefaults.standard

just use the shared UserDefaults for your AppGroup:

UserDefaults(suiteName: <your_app_group>)

Then you can read/write data like explained in this answer.

File Container

With the AppGroup entitlement you get access to the shared File Container:

let containerURL = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: <your_app_group>)!

and access an url like this:

let someFileURL = containerURL.appendingPathComponent("SomeFile.txt")

Then you can use your shared File Container like explained in this answer:

CoreData

You can create a shared CoreData container as well:

let storeURL = containerURL.appendingPathComponent("DataModel.sqlite")
let description = NSPersistentStoreDescription(url: storeURL)

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

Then you can use your shared CoreData Container like explained in this answer:


Here is a GitHub repository with different Widget examples including the App Group Widget.

One simple way to do this is by adding both the app and the widget to the same App Group, and then storing and retrieving data from UserDefaults storage located in that App Group's container instead of the default UserDefaults storage for the app. You can access this shared storage for your App Group by initializing UserDefaults using

UserDefaults(suiteName: "YOUR_APP_GROUP_NAME")

instead of accessing it using UserDefaults.standard.

This article gives a more thorough description of the details of this process.

Related