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,雙擊創建


這里隨便輸入你自己的命名,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

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。