WidgetKit @StateObject 不更新视图 [英] WidgetKit @StateObject not updating View
问题描述
我无法理解如何使我的 SwiftUI
数据模型示例与我的 Widget 一起使用.它在我的测试应用程序中运行良好,我立即观察到变化.当我尝试使用 Widget 时,我可以看到在控制台中打印的数据,但在 WidgetKit
中的 View
中没有发生任何更改.我正在使用 ObservableObject
类和 @Published
变量.我尝试使用 @StateObject
、@ObservedObject
和 @EnvironmentObject
并得到相同的结果.总是导致今天没有比赛.我的数据模型与 Combine
相关,不确定这是否与为什么我在 WidgetKit
的 View
中看不到数据更改有关>.
I'm having trouble understanding how to make my SwiftUI
data model example work with my Widget. It's working in my test app just fine, I observe changes immediately. When I attempt the Widget, I can see the data being printed in console but no changes are happening in my View
in WidgetKit
. I'm using a ObservableObject
class and @Published
variables. I've attempted to use a @StateObject
, @ObservedObject
and an @EnvironmentObject
and the same results. Always results in No game today. My data model is Combine
related, not sure if that has anything to do with why I can't see data changes in my WidgetKit
's View
.
SwiftUI 应用示例工作
struct ContentView: View {
@ObservedObject var data = CombineData()
@State private var showSortSheet: Bool = false
@State private var nhlTeams: TeamOrder = .NewYorkIslanders
var body: some View {
NavigationView {
VStack(alignment: .leading) {
if data.schedule?.dates.first != nil {
Text("Game today")
} else {
Text("No game today")
}
}
.listStyle(PlainListStyle())
.navigationBarTitle(Text(""), displayMode: .inline)
.navigationBarItems(leading: HStack {
Button(action: {
self.showSortSheet.toggle()
}) {
HStack {
Image(systemName: "arrow.up.arrow.down")
}
}
})
.actionSheet(isPresented: $showSortSheet) {
ActionSheet(title: Text("Teams:"), buttons: [TeamOrder.NewYorkIslanders, TeamOrder.MontrealCanadiens].map { method in
ActionSheet.Button.default(Text("\(method.rawValue)")) {
self.nhlTeams = method
data.fetchSchedule(self.nhlTeams.rawValue)
print("\(self.nhlTeams.rawValue)")
}
})
}
.onAppear {
data.fetchSchedule(self.nhlTeams.rawValue)
}
}
}
}
示例小部件 @StateObject
(无数据更改)
Example Widget @StateObject
(No data changes)
struct ExampleEntryView : View {
var entry: Provider.Entry
@Environment(\.widgetFamily) var widgetFamily
@StateObject var model = CombineData()
@ObservedObject var model = CombineData()
/*@EnvironmentObject private var model: CombineData*/
var body: some View {
VStack(alignment: .leading) {
if model.schedule?.dates.first != nil {
Text("Game today")
} else {
Text("No game today")
}
}
.onAppear {
model.fetchSchedule(entry.configuration.teams.rawValue) {
WidgetCenter.shared.reloadTimelines(ofKind: "NHL_Widget")
}
}
}
}
示例小部件 2 TimelineEntry(无数据更改)
struct SimpleEntry: TimelineEntry {
let date: Date
let configuration: ConfigurationIntent
let model: CombineData
}
struct Provider: IntentTimelineProvider {
func getTimeline(for configuration: ConfigurationIntent, in context: Context, completion: @escaping (Timeline<Entry>) -> ()) {
var entries: [SimpleEntry] = []
let currentDate = Date()
let model = CombineData()
let entryDate = Calendar.current.date(byAdding: .minute, value: 1, to: currentDate)!
let entry = SimpleEntry(date: entryDate, configuration: configuration, model: model)
entries.append(entry)
let timeline = Timeline(entries: entries, policy: .atEnd)
model.fetchSchedule(entry.configuration.teams.rawValue) {
completion(timeline)
}
}
}
struct ExampleEntryView : View {
var entry: Provider.Entry
@Environment(\.widgetFamily) var widgetFamily
var body: some View {
VStack(alignment: .leading) {
if entry.model.schedule?.dates.first != nil {
Text("Game today")
} else {
Text("No game today")
}
}
}
}
推荐答案
小部件是静态的,您在 getTimeline
上提供的视图将按原样显示且不会更新,因此在 onAppear
上调用 fetchSchedule
甚至不会被执行.一旦您在 getTimeline
中执行完成处理程序,就不会再执行任何代码.
Widgets are static, the view you provide on getTimeline
is what will be displayed as is and won't be updated, so the call to fetchSchedule
on onAppear
won't even be executed. Once you execute the completion handler in getTimeline
, no more code is executed.
要在小部件上显示数据,您需要在 getTimeline
中获取数据,创建一个从头开始显示数据的视图,并在完成处理程序中返回该条目.
To display data on your widgets you need to fetch your data in getTimeline
, create a view that displays the data from the start, and return that entry in your completion handler.
在您的最后一个示例中,我建议您在 model.fetchSchedule
的完成处理程序中创建条目并将 schedule
对象传递给您的视图.
In your last example I would suggest that you create your entry in the completion handler of model.fetchSchedule
and pass the schedule
object to your view.
这篇关于WidgetKit @StateObject 不更新视图的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!