引言

  前面的章节学完已经让我们可以顺利实现一个小组件了,但是小组件里面的数据如何刷新的呢,本节内容将讲解IOS的刷新机制。

大纲

  • 系统如何管理小组件刷新
  • Timeline刷新机制
  • Timeline刷新机制代码实现
  • 刷新策略建议
  • 时钟刷新策略(只有小时分钟,没有秒)
  • 主动请求重新刷新

系统如何管理小组件刷新

  1. WidgetKit在一个单独的进程中渲染小组件视图
  2. 即使小组件窗口显示在屏幕上,widget extension 也不会持续处于活动状态
  3. 为了管理系统负载,WidgetKit使用预算来分配一天中的窗口小组件重载
  4. WidgetKit为用户添加到其设备的每个活动小组件维护不同的预算
  5. 每日预算通常包括40到70次刷新。该速率大致可转换为小组件每15至60分钟重新加载一次,但是由于涉及到许多因素,因此这些时间间隔是不固定的。

综上所述,小组件的刷不能由开发者自由控制,官方建议如下:

  1. 如果您的小组件可以预测应重新加载的时间点,则最好的方法是为尽可能多的将来日期生成时间线。
  2. 时间轴中的条目间隔应保持尽可能大。
  3. 时间轴应创建至少相隔5分钟的时间轴条目。
  4. WidgetKit可能会在多个窗口小组件之间合并重新加载,从而影响窗口小组件重新加载的确切时间。

Timeline刷新机制



该图显示了WidgetKit请求时间线,提供程序生成时间线以及3小时后的时间进度,之后WidgetKit请求新的时间线



该图显示了WidgetKit请求时间线,提供程序生成时间线以及WidgetKit在2小时后请求新时间线的图

Timeline刷新机制代码实现(新增组件时,系统默认就实现了)

func getTimeline(for configuration: TimeTypeConfigurationIntent, 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 {
// 下面这个代码表示,在当前日期上加上 hourOffset 个小时得到一个新的日期
// .hour可以换成 .second .minute .day 等
        let entryDate = Calendar.current.date(byAdding: .hour, value: hourOffset, to: currentDate)!
        let entry = SimpleEntry(date: entryDate, configuration: configuration)
        entries.append(entry)
    } // 调用回调方法把生成好的时间线数据传递给系统
// policy 表示刷新策略
// .atEnd 表示,所有的时间线条目完成之后重新刷新一次,表现就是这个getTimeline方法被回调一次
// .after(date: Date) 表示,多久时间结束后再刷新一次
// .never表示时间轴走完就不刷了
    let timeline = Timeline(entries: entries, policy: .atEnd)
    completion(timeline)
}

备注:

  网上大部分资料都写着Timeline时间轴相隔5分钟,即每次创建5分钟内的刷新条目,但是小组件预算每日40到70次刷新,假设按70次算,总时间70 * 5 = 350分钟,大约6个小时就把次数用完了。所以大部分情况5分钟的间隔确实可以满足了,但是难免还是有用户把这个限制次数用完了。保险起见,尽量把时间间隔扩大,如果内存消耗不大,可以把间隔控制在60分钟,时间轴上每个条目间隔1分钟。这样几乎不会把系统给小组件的预算刷新次数给用完。

  正是因为IOS系统对小组件有刷新次数有限制和内存方面的限制(官网没有找到,但是看到网友们说是30M左右的限制,自己使用过程中也发现了占用内存过多导致进程被挂起,小组件就展示不出来了),所以没控制好刷新策略的话,可能经常会出现小组件界面展示不出来,或者过了一段时间之后,小组件直接不刷新了。

刷新策略建议

  1. 每次刷新时,时间轴准备好15-60分钟的刷新数据,最少是5分钟
  2. 时间轴每个刷新条目时间间隔尽可能大,时钟内组件间隔可以设置为1分钟
  3. 条目数量不宜过多,越少越好,时钟组件最多60左右
  4. 不要在5分钟内创建300个条目来做时钟按秒刷新,大概率会失败

时钟刷新策略(只有小时分钟,没有秒)

static func prepareEntriesEveryMinute(_ completion: @escaping (Timeline<WidgetEntry>) -> ()) {
    // 第一次刷新时间:延迟2秒刷
    let firstDate = Provider.getFirstEntryDate()
    // 第二次刷新时间:第一个整分钟时刷
    let firstMinuteDate = Provider.getFirstMinuteEntryDate()
   
    var entries: [WidgetEntry] = []
    entries.append(WidgetEntry(date: firstDate))
    entries.append(WidgetEntry(date: firstMinuteDate))
   
    // 后面以第一个整点分钟开始,每次加一分钟刷
    for minuteOffset in 1 ..< 60 {
        guard let entryDate = Calendar.current.date(byAdding: .minute, value: minuteOffset, to: firstMinuteDate) else {
            continue
        }
        entries.append(WidgetEntry(date: entryDate))
    }
    let timeline = Timeline(entries: entries, policy: .atEnd)
    completion(timeline)
} static func getFirstEntryDate() -> Date {
    let offsetSecond: TimeInterval = TimeInterval(2)
    var currentDate = Date()
    currentDate += offsetSecond
    return currentDate
} // 获取第一个分钟时间点所处的时间点
static func getFirstMinuteEntryDate() -> Date {
    var currentDate = Date()
    let passSecond = Calendar.current.component(.second, from: currentDate)
    let offsetSecond: TimeInterval = TimeInterval(60 - passSecond)
    currentDate += offsetSecond
    return currentDate
}

主动请求重新刷新

如果在App中修改了小组件的数据,可以通过如下的方式主动触发WidgetKit刷新小组件。

// 指定刷新哪个组件
WidgetCenter.shared.reloadTimelines(ofKind: "com.mygame.character-detail")
// 刷新全部组件
WidgetCenter.shared.reloadAllTimelines()

结语

  小组件的刷新,官方文档都没有明确说明到底是什么具体的规则,只说了有各种限制,系统会动态管理。所以在实际开发中可能会遇到小组件数据不刷新的问题,遇到这种情况,请减少Timeline中的条目数量,优化内存,确保小组件代码里面没有异常。小组件运行在单独的进程,如果异常会导致小组件进程卡死了,一个小组件出问题,其他小组件都不刷新了。既然刷新这么难控制,怎么实现数字时钟按秒刷新呢?下一节揭晓。

IOS Widget(5):小组件刷新机制的更多相关文章

  1. IOS小组件(6):小组件实现时钟按秒刷新

    引言   上一节中我们了解了IOS小组件的刷新机制,发现根本没法实现按秒刷新,但是看别的App里面有做到,以为用了什么黑科技,原来是因为系统提供了一个额外的机制实现时间的动态更新,不用走小组件的刷新机 ...

  2. IOS小组件(8):App与Widget数据共享

    引言   Widget是一个迷你版的App,IOS有沙盒机制,不同App之间无法直接共享数据.组件和主App之间其实就是不同App的关系,所以也无法通过userdefaults.standard来传数 ...

  3. IOS Widget(3):SwiftUI开发小组件布局入门

    引言   经过上一篇文章,我们已经可以在桌面上展示出一个小组件出来了,你肯定想小试牛刀,动手改一改,那我们就从改小组件的布局做起吧.本文不会讲解Swift语法,如果是熟悉Flutter,Kotlin这 ...

  4. IOS Widget(4-1):创建可配置小组件(静态配置数据)

    引言   经过前面几篇文章阅读,已经掌握开发一款小组件的基本技能了,接下来开始掌握一些相对高级一点的技能.本文创建一个可配置小组件,通过修改时间类型,让Text空间显示不同格式的时间. 本文大纲 添加 ...

  5. Android Widget小组件开发(一)——Android实现时钟Widget组件的步骤开发,这些知识也是必不可少的!

    Android Widget小组件开发(一)--Android实现时钟Widget组件的步骤开发,这些知识也是必不可少的! PS:学习自某网站(不打广告) 这个小组件相信大家都很熟悉吧,以前的墨迹天气 ...

  6. iOS阶段学习第34天笔记(UI小组件 UISegment-UISlider-UIStepper-UIProgressView-UITextView介绍)

    iOS学习(UI)知识点整理 一.UI小组件 1.UISegmentedControl 分段选择器  实例代码 - (void)viewDidLoad { [super viewDidLoad]; / ...

  7. Widget小组件

    一.使用步骤: 1.建立Widget的样式布局文件widght,布局只支持几种,比如,相对布局,线性布局,帧布局,布局里支持的控件也是有限的. 2.在res下建立一个新的文件夹我的命名为xml 3.在 ...

  8. Android开发工程师文集-1 小时学会Widget小组件开发

    前言 大家好,给大家带来Android开发工程师文集-1 小时学会Widget小组件开发的概述,希望你们喜欢 学会用Widget (小组件) Widget小组件很方便,很快捷,可以个性化,自己定制,相 ...

  9. jq 自定义标注小组件 $.widget

    html 部分 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www ...

随机推荐

  1. 涂鸦基于OAuth2在开发者平台上的探索与实践

    前言 开发授权(OAuth2)是一个开放标准,允许用户让第三方应用访问该用户在某一网站上存储的私密的资料(如照片.视频.联系人列表),而无需将用户名和密码提供给第三方应用. OAuth2允许用户提供一 ...

  2. spring-boot记录sql探索

    目标记录每次请求内的http.es.mysql耗时,本篇讨论mysql部分 为什么说要探索,这不是很简单的事么?但是能满足以下几点么? 能记录limit等参数 能将参数和sql写一起,能直接使用 能记 ...

  3. .Net5下WebRequest、WebClient、HttpClient是否还存在使用争议?

    WebRequest.WebClient.HttpClient 是C#中常用的三个Http请求的类,时不时也会有人发表对这三个类使用场景的总结,本人是HttpClient 一把梭,也没太关注它们的内部 ...

  4. sqli-labs系列——第二关

    less2 and 1=1有回显,and 1=2无回显,为数值型注入 order by 4–+报错,有3行 查询数据库名 ?id=0' union select 1,(select group_con ...

  5. SDK音频测试流程

    概述 在上篇文章中,给小伙伴们讲述了sdk模板在渲染中的流程,我们简单来回顾一下,主要讲述了数据创建.素材替换.音频.文字等四部分,在上次讲述中也因为时间于原因没有特别仔细的去讲述他们.上次我们说到最 ...

  6. rpm 命令介绍

    1. rpm 命令常用选项说明 1.1 功能模式选项 命令 解释 -i --install 安装软件,例:rpm -ivh tree-1.6.0-10.el7.x86_64.rpm -U --upgr ...

  7. 生产中常用的du命令

    1. 介绍 du是用来查看文件或目录所占用磁盘空间的大小 du [-abcDhHklmsSx] [-L <符号连接>][-X <文件>][--block-size][--exc ...

  8. 学习笔记-vue.js快捷登录 enter

    一般监听在输入密码的input监听keyup事件,加enter修饰符.如果input是组件,加上.native修饰符.<div id="app"> <input ...

  9. Sql Server Report Service访问服务页面503解决方法

    这个问题可能性比较多,也有多个方案去解决,可以从如下方法里逐个测试 1.打最新的数据库补丁. 2.删除报表服务配置的密钥,重启报表服务. 3.修改报表服务器配置的用户账户为域管理员 4.找到报表服务器 ...

  10. Dynamics CRM与ADFS安装到同一台服务器后ADFS服务与Dynamics CRM沙盒服务冲突提示808端口占用问题

    当我们安装Dynamics CRM的产品时如果是单台服务器部署而且部署了IFD的情况会遇到一个问题就是ADFS服务的监听端口和Dynamics CRM沙盒服务的端口冲突了. 这样会导致两个服务中的一个 ...