【iOS小组件】对Timeline时间线的理解

1,034 阅读3分钟

Timeline


时间线Timeline)是小组件刷新数据的机制。开发者可以在时间线提供者中动态生成不同时间点的条目,并设置更新策略。

简单来说时间线(Timeline)就是告诉系统,你需要小组件在什么时间展示什么内容。

struct Provider: TimelineProvider {
    ...
    func getTimeline(in context: Context, completion: @escaping (Timeline<Entry>) -> ()) {
        var entries: [SimpleEntry] = []

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

小组件通过 Provider 实现的 funcgetTimeline(in:,completion:) 方法提供所需刷新数据对象 Timeline,并通过 completion 回调返回。

Timeline时间线属性:

刷新数据所需的 时间和内容 被封装在实现 TimelineEntry 协议的结构体 SimpleEntry 中:

image.png

Timeline 是一个以 TimelineEntry 为元素的数组,每个条目都可以指定更新小组件内容的日期和时间。

举个例子,例如设置9 点刷新一次,9 点半刷新一次,10:05 刷新一次,大概是下面这个图:

image.png

更新策略


struct Provider: TimelineProvider {
    ...
    func getTimeline(in context: Context, completion: @escaping (Timeline<Entry>) -> ()) {
        ...
        let timeline = Timeline(entries: entries, policy: .atEnd)
        completion(timeline)
    }
}

小组件的更新策略同样配置在 Timeline 中,不同的刷新策略决定不同的时间线更新时机

public struct TimelineReloadPolicy : Equatable {

    /// A policy that specifies that WidgetKit requests a new timeline after
    /// the last date in a timeline passes.
    public static let atEnd: TimelineReloadPolicy

    /// A policy that specifies that the app prompts WidgetKit when a new
    /// timeline is available.
    public static let never: TimelineReloadPolicy

    /// A policy that specifies a future date for WidgetKit to request a new
    /// timeline.
    public static func after(_ date: Date) -> TimelineReloadPolicy
}

更新策略 policy 是一个 TimelineReloadPolicy 结构体,包含3种类型:

  • atEnd:当时间线内最后一个条目被用完后,系统将自动请求新的数据

  • never:永远不会向小组件请求新的时间线

  • after:可以指定一个未来的时间点,这个时间过后重新请求新时间线

例如,模版示例代码中设置了一个策略为 .atEnd,意味着当时间线的最后一个条目被用完后,系统将自动请求新的数据。

struct Provider: TimelineProvider {
    ...
    func getTimeline(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)!
            let entry = SimpleEntry(date: entryDate, emoji: "😀")
            entries.append(entry)
        }

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

刷新机制

所谓的小组件刷新,其实是刷新了 Timeline,导致由 Timeline 数据驱动的小组件视图发生了改变。小组件的刷新机制可分为两种:

  • System reloads:系统刷新

  • App-driven reloads:主App驱动刷新

1.System reloads

由系统发起的 Timeline 刷新,系统决定每个不同的 Timeline 的刷新频次。

System reloads刷新限制:

  • 系统刷新机制遵循 Timeline 更新策略,但不完全按照设置的日期时间刷新,具体时间看系统内部调用时机。

  • 超过频次的刷新请求将不会生效。

  • 高频使用的小组件可以获得更多的刷新频次。

以 24 小时为一个周期,每天能刷新多少次取决于三个条件:

  • 小组件向用户进行显示的频率和次数。

  • 小组件的上次重新载入时间。

  • 小组件的包含 App 是否处于活跃状态。

对于用户经常查看的小组件,每日最大的刷新次数为 40 到 70 次大致换算为每 15 到 60 分钟重载一次小组件

2.App-driven reloads

由 App 触发小组件 Timeline 刷新。

  • 当App在后台时,后台推送可以触发 reload

  • 当App在前台时,通过 WidgetCenter 可以主动触发 reload

image.png

App-driven reloads 可以通过 WidgetCenter 手动刷新时间线

刷新所有时间线:

WidgetCenter.shared.reloadAllTimelines()

刷新指定小组件:

// xx 为小组件的kind
WidgetCenter.shared.reloadTimelines(ofKind: "xx")

参考

juejin.cn/post/729168…

本文同步自微信公众号 "程序员小溪" ,这里只是同步,想看及时消息请移步我的公众号,不定时更新我的学习经验。