这里事先说明一下,Intent是用户可以对小组件widget做一些调整。这里的调整在长按小组件时,点击出现的“编辑小组件”,然后进行的操作。
如下图:
现在来看代码:
import WidgetKit
import SwiftUI
import Intents
//数据结构
struct SimpleEntry: TimelineEntry {
let date: Date
//这里需要注意,ConfigurationIntent是预先设定好的,代码如下:
// public class ConfigurationIntent: INIntent {
//
// }
let configuration: ConfigurationIntent
}
//Provider提供placeholder(占位符)、getSnapshot(快照)和getTimeline(时间线)
struct Provider: IntentTimelineProvider {
//定义占位符—
//参数前要加in,返回值为之前定义的SimpleEntry结构——这里的返回值就是SimpleEntry本身,意思就是不改变原视图
func placeholder(in context: Context) -> SimpleEntry {
SimpleEntry(date: Date(), configuration: ConfigurationIntent())
}
//定义快照
//@escaping表示逃逸闭包,就是在返回值之后执行的闭包。也就是在函数执行并且返回完返回值才执行的闭包。
//这里的逃逸闭包是以结构体SimpleEntry为参数,返回值为空。
// - Parameters:
// - configuration: The intent containing user-customized values.
// - context: An object describing the context to show the widget in.
// - completion: The completion handler to call after you create the
// snapshot entry.
// - 参数:
// - configuration: 包含用户定义值的意图。(这个参数需要预先定义,这里是在SimpleEntry结构体里)
// - context: 一个描述什么会显示在widget上的对象
// - completion: 一个完成代理(completion handler)在你创建snapshot(快照)后被调用。
func getSnapshot(for configuration: ConfigurationIntent, in context: Context, completion: @escaping (SimpleEntry) -> ()) {
//创建快照entry
let entry = SimpleEntry(date: Date(), configuration: configuration)
//定义完成代理调用快照entry
completion(entry)
}
//定义时间线
//这里的逃逸闭包是以结构体SimpleEntry为参数,返回值为空。
func getTimeline(for configuration: ConfigurationIntent, in context: Context, completion: @escaping (Timeline<Entry>) -> ()) {
//定义一个数组entries,里面存着的就是时间线上不同时间生成的界面
//格式是[],里面是结构体SimpleEntry的内容
var entries: [SimpleEntry] = []
//生成一个时间线,包含了五个entry,每个相隔一小时,从当前日期开始。
//entry相当于一个视图的数据
// Generate a timeline consisting of five entries an hour apart, starting from the current date.
let currentDate = Date()
for hourOffset in 0 ..< 5 {
let entryDate = Calendar.current.date(byAdding: .calendar, value: hourOffset, to: currentDate)!
let entry = SimpleEntry(date: entryDate, configuration: configuration)
//然后将生成的entry放入数组entries中,也就是放入时间线中
entries.append(entry)
}
let timeline = Timeline(entries: entries, policy: .atEnd)
//定义完成代理调用时间线timeline
completion(timeline)
}
}
//设计界面————就和一般的SwiftUI设计界面一样
struct WidgetViewEntryView : View {
var entry: Provider.Entry
var body: some View {
Text(entry.date, style: .time)
}
}
//Widget(小组件)部分
//@main表示最先显示该界面
@main
struct WIdgetView: Widget {
let kind: String = "1"
var body: some WidgetConfiguration {
IntentConfiguration(kind: kind, intent: ConfigurationIntent.self, provider: Provider()) { entry in
//将设计好的WidgetViewEntryView
WidgetViewEntryView(entry: entry)
}
//编辑小组件的时候显示的名称
.configurationDisplayName("小组件名称")
//编辑小组件的时候显示的描述
.description("这是一段显示小组件描述的文本")
//该小组件支持哪些尺寸
.supportedFamilies([.systemSmall, .systemMedium])
}
}
//预览
struct WidgetView_Previews: PreviewProvider {
static var previews: some View {
WidgetViewEntryView(entry: SimpleEntry(date: Date(), configuration: ConfigurationIntent()))
.previewContext(WidgetPreviewContext(family: .systemSmall)
}
}