iOS14 widget开发,动态编辑功能,时间不准问题记录

要开发新的 Widget 组件, 首先你要准备 Xcode 12 Beta 版本, 以及一台安装了 iOS 14 Beta 版本的设备, 或者直接使用模拟器.

1.在 Xcode 12 中创建一个新项目, 并且在项目设置页面里,点击左下角的箭头创建新的 Target:

2.在弹出的组件选择窗口中, 在右上角的搜索栏中输入 widget , 然后在过滤后列表中选中 Widget Extension , 点击 Next 继续.

2.接着, 输入 widget 的名称, 根据需求选择 Include Configuration Intent 的选择, 点击 Finish

不勾选小组件事没有编辑功能的,我的项目是需要勾选的

3,勾选之后创建项目会多出来这些


4.默认Widget文件结构分析

1)@main
struct WidgetUI: Widget {
    
    let kind: String = "WidgetUI"

     var body: some WidgetConfiguration {
        
      return  IntentConfiguration(kind: kind,

这里就是widget的main入口函数了,不勾选ConfigurationIntent 这里应该是个staictConfiguration

 

    func placeholder(in context: Context) -> SimpleEntry {

2)Provider主要用于数据刷新

     placeholder :系统让你的 view 自动渲染一个占位图。

   getSnapshot:快照预览为了在小部件库中显示小部件,在你添加widget时候,预览的样式。当部件还没有从服务器获取状态    时,Provider通过显示一个空状态来实现getSnapshot方法。

getTimeline:在请求初始快照后,WidgetKit调用getTimeline(for:with:completion:)向提供者请求一个常规的时间线。时间线由一个或多个时间线条目和一个重载策略组成,告知WidgetKit何时请求后续时间线。

  Widget的刷新策略

    Timeline里面有三种方式:atEnd,after(date),never

  • atEnd: timeline 中最后一个 entry 显示后更新。timelines 方法会重新调用。
  • after(date): 指定日期,重新更新timeline。
  • never:系统不会自动更新,除非我们主动通过 Widget Center Api 来更新

所以要是做时钟时间空间就要刷新的频繁了 in 0 ..< 60

 let entryDate = Calendar.current.date(byAdding: .second, value: hourOffset, to: currentDate)!

 

3)SimpleEntry 就是数据了,像电量及时刷新的数据可以放到里面

struct SimpleEntry: TimelineEntry {
    let date: Date
    let configuration: ConfigurationIntent

    let batteryLevel: Float

}

4)WidgetUIEntryView这里就是写页面布局的地方了

5)编辑功能有静态和动态的

静态的不用勾选Dynamic 选择所需要的类型在表里面添加所需要的数据

如选择枚举类型进行添加type1,type2,编辑小组件的时候会出现type1,type2选择的列表

我这里用的是动态的

动态的需要加另外一个extension

会出现

class IntentHandler: INExtension, ConfigurationIntentHandling{
    
    func provideModelOptionsCollection(for intent: ConfigurationIntent, with completion: @escaping (INObjectCollection<LRDModel>?, Error?) -> Void) {

     let collection = INObjectCollection(items:list)
        completion(collection, nil)

}

在这里可以返回你所需的动态数据,当然返回的是之前定义数据类型的一个集合

可以用UserDefaults.init(suiteName:)或者 FileManager 与主app进行数据共享

在获取文件路径转字符串时用.path 不要用absoluteString 返回的结果不一样

.path file:/Users/admin/Library/

absoluteString

file:///Users/admin/Library/

补充:

之前在刷新控件的时候用的是

let timeline = Timeline(entries: entries, policy: .atEnd)这种机制

填充entry使时间一秒一秒的变化,做到时间准确,(有的说可以),但是我这边总是有时候会停止一段时间,然后在刷新,widget是有自己的刷新机制的,并不会按照要求刷新的那么快

于是换了思路(当然如果你的是时间包括显示秒的话这种是不行的,只能精确到分钟,秒动的话可以使用text 的timer)

let timeline = Timeline(entries: entries, policy: .after(entryDate))

这种方式

记录当前启动widget使距离整分剩余的秒数

let lastSecond = Int(currentDate.timeIntervalSince1970)%60

let intSecond :Int = 60 - lastSecond

这里填充20分钟的数据

  for secondOffset in 0 ..< 20{

                     if secondOffset == 0{
                        /// 第一条用当前时间
                        let entry = SimpleEntry(date: currentDate, ...);
                        entries.append(entry)
                    }else if secondOffset == 1{
                   
  /// 第二条用剩余的秒数凑够一分钟
                        let entryDate = Calendar.current.date(byAdding: .second, value: intSecond , to: currentDate)!
                        let entry = SimpleEntry(date: entryDate, .....)
                        entries.append(entry)
                    } else{
                        /// 用当前时间 - 非整分钟 ,之后按整分钟数据添加
                        let entryDate = Calendar.current.date(byAdding: .minute, value: hourOffset, to: currentDate - TimeInterval(lastSecond))!
                        let entry = SimpleEntry(date: entryDate.....)
                        entries.append(entry)
                    }

// 填充的数据不到20分钟,这里我用了15分钟之后再刷新

let entryDate = Calendar.current.date(byAdding: .minute, value: 15, to: currentDate)!
                let timeline = Timeline(entries: entries, policy: .after(entryDate))

}

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值