expect:
- app update UserDefaults use group value.
- widget use NotificationCenter.default observe same group UserDefaults, then reloadTimeline
actual:
- successfully set
- no reload happen, and I try set same key to another value inside the selector function to test whether it's been called. provided the selector not work.
steps:
- click a app button to set a key of UserDefaults
- back home , widget no change - expect it update view based one new value
- rebuild widget , can see the ui use new value - prove set call successfully but notification of UserDefaults.didChangeNotification not send
host app :
UserDefaults(suiteName: "group.a")
store?.setValue("a", forKey: "target")
widget:
class NotiWatch {
init(){
NotificationCenter.default.addObserver(self, selector: #selector(onchange), name: UserDefaults.didChangeNotification, object: nil)
}
@objc func onchange(notification: NSNotification) {
UserDefaults(suiteName: "group.a")?.set("cccc", forKey: "target")
WidgetCenter.shared.reloadAllTimelines()
}
deinit{
NotificationCenter.default.removeObserver(self, name: UserDefaults.didChangeNotification, object: nil)
}
}
struct Provider: TimelineProvider {
let def:UserDefaults? ;
let watcher = NotiWatch()
init(){
let fmt = DateFormatter()
fmt.dateFormat = "yyyy-MM-dd HH:mm"
dd = fmt.date(from: "2070-12-20 23:59")!
def = UserDefaults(suiteName: "group.a") ;
}
var dd = Date()
func placeholder(in context: Context) -> SimpleEntry {
SimpleEntry(date: Date(), unit: "Y",left: 0,tar: "")
}
func getSnapshot( in context: Context, completion: @escaping (SimpleEntry) -> ()) {
let date = Date()
let left = dd.timeIntervalSince(date).minutes
let entry = SimpleEntry(date: date, unit: "M",left: left,tar: "")
completion(entry)
}
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 tar = def?.string(forKey: "target") ?? ""
let currentDate = Date()
for offset in 0 ..< 60 {
let entryDate = Calendar.current.date(byAdding: .minute, value: offset, to: currentDate)!
let left = dd.timeIntervalSince(entryDate).minutes
let entry = SimpleEntry(date: currentDate, unit: "minutes",left:left,tar: tar)
entries.append(entry)
}
let timeline = Timeline(entries: entries, policy: .atEnd)
completion(timeline)
}
}