在iOS 14的SwiftUI中,如何在主应用程序和小部件之间共享数据?

26
@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.")
    }
}

我该如何将主应用程序的数据传递给小部件?

2个回答

59

你可以为你的小部件和应用程序同时添加AppGroup功能(这里有一个非常好的解释如何添加它)。


UserDefaults

不要使用

UserDefaults.standard

只需使用共享的UserDefaults来为您的AppGroup存储数据:
UserDefaults(suiteName: <your_app_group>)

您可以像这个答案中所解释的那样读/写数据。

文件容器

使用AppGroup授权,您可以访问共享的文件容器:

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

访问像这样的URL:

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

然后,您可以像在这个答案中解释的那样使用共享文件容器:

CoreData

您也可以创建一个共享的 CoreData 容器:

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

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

接着你可以像这个答案所解释的那样使用共享的CoreData容器:


这里有一个包含不同小部件示例(包括应用组小部件)的GitHub存储库


请问您可以告诉我在哪里放置那段代码(共享的CoreData容器)吗?如果可以的话,请分享一个代码片段,其中显示了小部件中的获取部分。 - umayanga
1
@umayanga 这里真的没有任何特定于Widget的内容。您可以像在标准应用程序中一样创建Persistent Container(只需明确指定sqlite文件的位置)。获取部分也是如此。您可以从Persistent Container中访问上下文并使用它执行fetch请求。但是,由于这可能仍然令人困惑,因此我在您的帖子下添加了更详细的说明。 - pawello2222

3

一种简单的方法是将应用和小部件都添加到同一个应用组中,然后从该应用组容器中的UserDefaults存储中存储和检索数据,而不是默认的应用程序UserDefaults存储。 您可以通过使用以下方式初始化UserDefaults来访问此共享存储:

UserDefaults(suiteName: "YOUR_APP_GROUP_NAME")

使用UserDefaults.standard访问它的替代方法。

本文提供了更详细的过程描述。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接