pas*_*tgt 7 ios swift healthkit widgetkit swiftui
我正在HealthKit我的小部件中使用数据。如果手机被锁定,则无法获取HealthKit数据,除非手机解锁。但是,即使手机被锁定,我的小部件时间线也会尝试更新。
是否有可能以某种方式返回空完成,因此它将保持当前小部件数据不变?
这是我的代码:
struct Provider: IntentTimelineProvider {
private let healthKitService = HealthKitService()
func getTimeline(for configuration: ConfigurationIntent, in context: Context, completion: @escaping (Timeline<Entry>) -> ()) {
let currentDate = Date()
let refreshDate = Calendar.current.date(byAdding: .minute, value: 5, to: currentDate)!
healthKitService.getHeartRate() { data, error in
//Create an empty entry
var entry = SimpleEntry(date: currentDate, configuration: ConfigurationIntent(), data: nil)
//If no errors, set data
if(error == nil) {
entry.data = data
} else {
print(error) //this runs when a locked phone does the widget update
}
//Return response
let timeline = Timeline(entries: [entry], policy: .after(refreshDate))
completion(timeline)
}
}
}
Run Code Online (Sandbox Code Playgroud)
我能做的就是存储条目数据并将UserDefaults其加载到错误路径中?我不确定这是否是一个好的解决方案。
主要问题是函数中没有状态getTimeline。这与如何在小部件 iOS14 中刷新多个计时器?中的问题类似。- 您需要某种方式在外部存储信息getTimeline。
正如您已经提到的,一个可能的解决方案是将最后一个条目存储在UserDefatuls.
但是,您也可以尝试创建自己的EntryCache:
class EntryCache {
var previousEntry: SimpleEntry?
}
Run Code Online (Sandbox Code Playgroud)
struct SimpleEntry: TimelineEntry {
let date: Date
var previousDate: Date?
}
Run Code Online (Sandbox Code Playgroud)
struct IntentProvider: IntentTimelineProvider {
private let entryCache = EntryCache()
// ...
// in this example I'm testing if the `previousDate` is loaded correctly from the cache
func getTimeline(for configuration: TestIntentIntent, in context: Context, completion: @escaping (Timeline<SimpleEntry>) -> Void) {
let currentDate = Date()
let entry = SimpleEntry(date: currentDate, previousDate: entryCache.previousEntry?.date)
let refreshDate = Calendar.current.date(byAdding: .minute, value: 1, to: currentDate)!
let refreshEntry = SimpleEntry(date: refreshDate, previousDate: entryCache.previousEntry?.date)
let timeline = Timeline(entries: [entry, refreshEntry], policy: .atEnd)
// store the `entry` in the `entryCache`
entryCache.previousEntry = entry
completion(timeline)
}
}
Run Code Online (Sandbox Code Playgroud)
笔记
我没有找到任何关于何时TimelineProvider可以重新创建的信息。在我的测试中,Widget 在Provider每次刷新时都使用相同的内容,但更安全的做法是假设 Provider 可能会在将来的某个时刻重新初始化。那么,理论上,对于一个刷新周期,previousEntry将为nil。