iOS 14 小组件(3):WidgetExtension 长按

2020-11-02  本文已影响0人  Maojunhao

1. 基本介绍

Widget Extension 创建看这里 -> iOS 14 小组件(1):WidgetExtension 创建及报错详解

这一篇介绍一下如何处理长按的弹出框以及网络数据交互更新。

2. 效果展示

Edit Widget Extension.gif

3. 网络数据处理

其实小组件刷新原理很简单,流程就是 Provider -> Entry -> EntryView,这么个逻辑。我们在 Provider 中更新 entry 的属性,然后在 EntryView 中可以拿到这个 entry,于是就可以完成数据的更新展示,当然 entry 的属性参数都是可以自定义的。

这里我就只写一下网络数据的处理,至于 Request 请求,我就不找虚拟接口来处理了。

import WidgetKit
import SwiftUI
import Intents

struct Provider: IntentTimelineProvider {
    
    let response = ResponseObject(test1: "default_test1", test2: "default_test2")
    
    
    func placeholder(in context: Context) -> SimpleEntry {
        SimpleEntry(date: Date(), configuration: ConfigurationIntent(), response: response)
    }

    func getSnapshot(for configuration: ConfigurationIntent, in context: Context, completion: @escaping (SimpleEntry) -> ()) {
        let entry = SimpleEntry(date: Date(), configuration: configuration, response: response)
        completion(entry)
    }

    func getTimeline(for configuration: ConfigurationIntent, in context: Context, completion: @escaping (Timeline<Entry>) -> ()) {
        var entries: [SimpleEntry] = []

        // 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: .hour, value: hourOffset, to: currentDate)!
            
            // 在这里做网络请求,拿到请求结果 netResponse 用来更新页面
            let netResponse = ResponseObject(test1: "net_test1", test2: "net_test2")
            let entry = SimpleEntry(date: entryDate, configuration: configuration, response: netResponse)
            entries.append(entry)
        }

        let timeline = Timeline(entries: entries, policy: .atEnd)
        completion(timeline)
    }
}

struct ResponseObject {
    let test1 : String
    let test2 : String
}


struct SimpleEntry: TimelineEntry {
    let date: Date
    let configuration: ConfigurationIntent
    let response : ResponseObject
    
}

struct WidgetExEntryView : View {
    var entry: Provider.Entry

    var body: some View {
        ZStack(alignment: .leading, content: {
            Image("widgetImage")
                .frame(width: 100, height: 100, alignment: .center)
            
            HStack(alignment: .center, spacing: 15, content: {
                
                Image("xcode")
                
                VStack(alignment: .leading, spacing: 15, content: {
                    
                    Text(entry.response.test1)
                        .foregroundColor(.white)
                    
                    Text(entry.response.test2)
                        .foregroundColor(.white)
                        .lineLimit(2)
                })
                
            })
        }).widgetURL(URL(string: "widget://test/widgetImage"))
    }
}

@main
struct WidgetEx: Widget {
    let kind: String = "WidgetEx"

    var body: some WidgetConfiguration {
        IntentConfiguration(kind: kind, intent: ConfigurationIntent.self, provider: Provider()) { entry in
            WidgetExEntryView(entry: entry)
        }
        .configurationDisplayName("My Widget")
        .description("This is an example widget.")
    }
}

struct WidgetEx_Previews: PreviewProvider {
    
    static var previews: some View {
        let response = ResponseObject(test1: "default_test1", test2: "default_test2")

        WidgetExEntryView(entry: SimpleEntry(date: Date(), configuration: ConfigurationIntent(), response: response))
            .previewContext(WidgetPreviewContext(family: .systemSmall))
    }
}

添加前效果图(注意图中文字变化)

default small.png default large.png

添加后效果图(注意图中文字变化)

net small medium.png

4. 长按交互

其实长按交互事件和代码没啥关系,主要是 .intentdefinition 文件的配置,我这里直接上图了。

Enum.png String.png Enum detail.png Type detail.png

效果图如下。

Edit Widget Image.png Edit Widget Extension.gif

5. 技术小结

上一篇 下一篇

猜你喜欢

热点阅读