iOS14|iOS14 Widget小组件开发实践1——了解Widget

iOS14带来了新的UI组件:WidgetKit,人称小组件(用过安卓的都能理解),这货的前身其实就是iOS10时候引入的Today Extension
Widget为应用程序提供了这样一种功能:其可以让用户在主屏幕上展示App中用户所关心的信息。例如一款天气软件,其可以附带一个Widget让用户在主屏幕就可查看今日的天气情况,例如股票相关的软件,用户将自己感兴趣的股票收藏,无需打开App,在主屏幕即可查到对应的股价信息。
刚好iOS14正式版更新的节奏,抽点时间来试试整一个Widget小组件玩玩。
Widget只支持SwiftUI实现,OC项目同样可以创建,但是必须用SwiftuUI实现。
创建 通过Xcode -> File -> New -> Target菜单路径找到 Widget Extension,双击创建

iOS14|iOS14 Widget小组件开发实践1——了解Widget
文章图片

这里随便输入你自己的命名, Include Configuration Intent这选项暂时不勾选,这选项主要是用来支持你自定义一些属性配置(例如天气组件,用户可以选择城市,股票组件,用户可以选择代码),不支持的话则不用勾选。
iOS14|iOS14 Widget小组件开发实践1——了解Widget
文章图片

之后在 Xcode的左侧项目目录可以看到,这里自动新增了一些东西,其中 TestWidget.swift文件就是我们即将编写代码实现的地方。
iOS14|iOS14 Widget小组件开发实践1——了解Widget
文章图片

先点进去看下 Xcode为我们生产的默认代码,然后运行跑一下,看看模拟器效果。
iOS14|iOS14 Widget小组件开发实践1——了解Widget
文章图片

iOS14|iOS14 Widget小组件开发实践1——了解Widget
文章图片

解读 【iOS14|iOS14 Widget小组件开发实践1——了解Widget】接下来看下Xcode生成的默认Widget实现代码
Provider Provider:为小组件展示提供一切必要信息的结构体,实现TimelineProvider协议
placeholder:提供一个默认的视图,当网络数据请求失败或者其他一些异常的时候,用于展示
getSnapshot:为了在小部件库中显示小部件,WidgetKit要求提供者提供预览快照,在组件的添加页面可以看到效果
getTimeline:在这个方法内可以进行网络请求,拿到的数据保存在对应的entry中,调用completion之后会到刷新小组件

struct Provider: TimelineProvider { func placeholder(in context: Context) -> SimpleEntry { SimpleEntry(date: Date()) }func getSnapshot(in context: Context, completion: @escaping (SimpleEntry) -> ()) { let entry = SimpleEntry(date: Date()) completion(entry) }func getTimeline(in context: Context, completion: @escaping (Timeline) -> ()) { 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) entries.append(entry) }let timeline = Timeline(entries: entries, policy: .atEnd) completion(timeline) } }

SimpleEntry 实现TimelineEntry协议,就是用来保存所需要的数据
struct SimpleEntry: TimelineEntry { let date: Date }

TestWidgetEntryView 这个结构体就是我们需要用来展示的视图View,这里可以进行各种界面搭建
struct TestWidgetEntryView : View { var entry: Provider.Entry var body: some View { Text(entry.date, style: .time) } }

@main struct TestWidget: Widget @main:代表着Widget的主入口,系统从这里加载
kind:是Widget的唯一标识
StaticConfiguration:初始化配置代码
configurationDisplayName:添加编辑界面展示的标题
description:添加编辑界面展示的描述内容
supportedFamilies这里可以限制要提供三个样式中的哪几个
@main struct TestWidget: Widget { let kind: String = "TestWidget"var body: some WidgetConfiguration { StaticConfiguration(kind: kind, provider: Provider()) { entry in TestWidgetEntryView(entry: entry) } .configurationDisplayName("My Widget") .description("This is an example widget.") //supportedFamilies不设置的话默认三个样式都实现 .supportedFamilies([.systemSmall, .systemMedium, .systemLarge]) } }

展示多个Widget 一个Widget只提供了三个样式的选择,比如我有个需求,我不需要这两个样式,但是我需要多个小的样式,那么就需要创建多个Widget了。
这时候就要用到WidgetBundle,把主入口@main转移到YourWidgets,实现WidgetBundle协议,这里返回多个Widget
@main struct YourWidgets: WidgetBundle { @WidgetBundleBuilder var body: some Widget { OneWidget() TwoWidget() ThreeWidget() ...... } }

未完待续,下一篇我们开始实现自己的小组件
参考资料 creating-a-widget-extension
TimelineProvider
https://swiftrocks.com

    推荐阅读