Share data between main App and Widget in SwiftUI
Asked Answered
E

2

29
@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?

Employer answered 16/9, 2020 at 14:17 Comment(0)
B
63

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.

Blennioid answered 16/9, 2020 at 17:20 Comment(2)
Can you please tell me where to put that code (shared CoreData container). If you can, please share a code snippet which shows the fetching part in a widget.Dulcy
@Dulcy There is really nothing Widget-specific here. You create a Persistent Container in the same way as in a standard App (you just explicitly specify the location of the sqlite file). The same applies to the fetching part. You access a context from a persistent container and perform a fetch request with it. But as this still might be confusing I added a more detailed explanation under your post.Blennioid
L
3

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.

Lachlan answered 5/2, 2021 at 0:20 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.