iOS14
帶來了新的UI組件:WidgetKit
,人稱小組件(用過安卓的都能理解),這貨的前身其實就是iOS10
時候引入的Today Extension
。
Widget
為應用程序提供了這樣一種功能:其可以讓用戶在主屏幕上展示App中用戶所關心的信息。例如一款天氣軟件,其可以附帶一個Widget
讓用戶在主屏幕就可查看今日的天氣情況,例如股票相關的軟件,用戶將自己感興趣的股票收藏,無需打開App,在主屏幕即可查到對應的股價信息。
剛好iOS14正式版更新的節奏,抽點時間來試試整一個Widget
小組件玩玩。
Widget
只支持SwiftUI
實現,OC
項目同樣可以創建,但是必須用SwiftuUI
實現。
創建
通過Xcode
-> File
-> New
-> Target
菜單路徑找到 Widget Extension
,雙擊創建
這里隨便輸入你自己的命名,
Include Configuration Intent
這選項暫時不勾選,這選項主要是用來支持你自定義一些屬性配置(例如天氣組件,用戶可以選擇城市,股票組件,用戶可以選擇代碼),不支持的話則不用勾選。之后在
Xcode
的左側項目目錄可以看到,這里自動新增了一些東西,其中TestWidget.swift
文件就是我們即將編寫代碼實現的地方。先點進去看下
Xcode
為我們生產的默認代碼,然后運行跑一下,看看模擬器效果。解讀
接下來看下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<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)
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