- Widget是iOS 14的新特性,要创建小组件,需要使用到SwiftUIQ和WidgetKit。要在项目中创建 Widget,首先点击此处的加号图标,添加一个target。

- 点击右侧的垂直滚动条,查看Widget扩展所在的位置。

- 选择此处的Widget Extension模板。

- 点击下一步,进入下一步设置页面。

- 输入Product Name。

- 取消勾选此处的复选框。如果Widget提供了用户可配置的属性,请勾选此处的选项。我们将在后面创建用户可配置的Widget。

- 点击完成按钮,完成Target创建。

- 点击激活按钮,激活Widget的scheme。这样当点击编译并运行按钮时,可以在模拟器中运行该 Widget。

- 点击此处箭头,显示Widget相关文件。

- 与Widget相关的文件都在这个文件夹里面。

- Provider是Widget的核心引擎。它负责向小组件提供数据、设置更新数据的时间间隔、设置在 Widget加载时显示的占位符视图,以及设置位于Widget库中的快照。

- 时间线功能用于创建一个或多个Entry。可以设置时间间隔,之后需要更新TimelineEntry。 SimpleEntry用来保存单个TimelineEntry数据,并最终显示在Widget上。

- Widget的内容设置在DemoWidgetEntryView的内部。@main属性表示DemoWidget是Widget的入口。

- kind是用于在Widget库中,将Widget与其他Widget区分开的标识符。StaticConfiguration表示不需要用户配置属性的Widget。例如,显示一般市场信息的股市Widget。

- 应用程序启动之后,在主屏幕上显示了刚刚创建的Widget,它显示了应用启动时的时间。我们可以添加不同尺寸的Widget,首先长按打开选项菜单。

- 选择此处菜单,使主屏幕进入编辑模式。

- 点击左上角+号按钮,打开小组件列表。

- 然后选择新创建的小组件。

- 在此处按下并向左侧拖动,显示中型尺寸的小组件。

- 点击此处的添加小组件按钮,往主屏幕添加一个中型尺寸的小组件。

- 此时在主屏幕上显示了两个不同尺寸的小组件,点击右上角的完成按钮,完成对主屏幕的编辑。

- 这样就创建了一个简单的小组件,我们将在下一节对项目进行修改,以创建更加强大的小组件。

源码:
import WidgetKit
import SwiftUI
import Intents
struct Provider: IntentTimelineProvider {
func placeholder(in context: Context) -> SimpleEntry {
SimpleEntry(date: Date(), configuration: ConfigurationIntent())
}
func getSnapshot(for configuration: ConfigurationIntent, in context: Context, completion: @escaping (SimpleEntry) -> ()) {
let entry = SimpleEntry(date: Date(), configuration: configuration)
completion(entry)
}
func getTimeline(for configuration: ConfigurationIntent, in context: Context, completion: @escaping (Timeline<Entry>) -> ()) {
var entries: [SimpleEntry] = []
let currentDate = Date()
for hourOffset in 0 ..< 5 {
let entryDate = Calendar.current.date(byAdding: .hour, value: hourOffset, to: currentDate)!
let entry = SimpleEntry(date: entryDate, configuration: configuration)
entries.append(entry)
}
let timeline = Timeline(entries: entries, policy: .atEnd)
completion(timeline)
}
}
struct SimpleEntry: TimelineEntry {
let date: Date
let configuration: ConfigurationIntent
}
struct DemoWidgetEntryView : View {
var entry: Provider.Entry
var body: some View {
Text(entry.date, style: .time)
}
}
@main
struct DemoWidget: Widget {
let kind: String = "DemoWidget"
var body: some WidgetConfiguration {
IntentConfiguration(kind: kind, intent: ConfigurationIntent.self, provider: Provider()) { entry in
DemoWidgetEntryView(entry: entry)
}
.configurationDisplayName("My Widget")
.description("This is an example widget.")
}
}
struct DemoWidget_Previews: PreviewProvider {
static var previews: some View {
DemoWidgetEntryView(entry: SimpleEntry(date: Date(),
configuration: ConfigurationIntent()))
.previewContext(WidgetPreviewContext(family: .systemSmall))
.previewDisplayName("Small widget")
}
}