问题描述
我在我的小部件中使用了 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)
}
}
}
我能做的是将条目数据存储在 UserDefaults
中并将其加载到错误路由中?我不确定这是否是一个好的解决方案。
解决方法
主要问题是您在 function getdata(){
var email=document.getElementById("email").value;
firebase.database().ref('0/'+email).once('value').then(function(snapshort){
var total=snapshort.val().total;
document.getElementById("total").innerHTML=total;
})}
函数中没有 state。这与 How to refresh multiple timers in widget iOS14? 中的问题类似 - 您需要某种方式将信息存储在 getTimeline
之外。
正如您已经提到的,一个可能的解决方案是将最后一个条目存储在 getTimeline
中。
不过,您也可以尝试创建自己的 UserDefatuls
:
EntryCache
class EntryCache {
var previousEntry: SimpleEntry?
}
struct SimpleEntry: TimelineEntry {
let date: Date
var previousDate: Date?
}
注意
我没有找到有关何时可以重新创建 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)
}
}
的任何信息。在我的测试中,Widget 每次刷新都使用相同的 TimelineProvider
,但更安全的做法是假设 Provider 可能会在未来某个时间点重新初始化。然后,理论上,对于一个刷新周期,Provider
将为 previousEntry
。