WidgetKit @StateObject 不更新视图
WidgetKit @StateObject not updating View
我无法理解如何使我的 SwiftUI
数据模型示例与我的 Widget 一起工作。它在我的测试应用程序中运行良好,我立即观察到变化。当我尝试使用 Widget 时,我可以在控制台中看到正在打印的数据,但是 WidgetKit
中的 View
没有发生任何变化。我正在使用 ObservableObject
class 和 @Published
变量。我尝试使用 @StateObject
、@ObservedObject
和 @EnvironmentObject
并得到相同的结果。总是导致今天没有比赛。我的数据模型与 Combine
相关,不确定这是否与为什么我在 WidgetKit
的 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
(无数据更改)
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
中执行完成处理程序后,不再执行任何代码。
要在小部件上显示数据,您需要在 getTimeline
中获取数据,创建一个从头开始显示数据的视图,然后 return 在完成处理程序中输入该条目。
在您的最后一个示例中,我建议您在 model.fetchSchedule
的完成处理程序中创建您的条目,并将 schedule
对象传递给您的视图。
我无法理解如何使我的 SwiftUI
数据模型示例与我的 Widget 一起工作。它在我的测试应用程序中运行良好,我立即观察到变化。当我尝试使用 Widget 时,我可以在控制台中看到正在打印的数据,但是 WidgetKit
中的 View
没有发生任何变化。我正在使用 ObservableObject
class 和 @Published
变量。我尝试使用 @StateObject
、@ObservedObject
和 @EnvironmentObject
并得到相同的结果。总是导致今天没有比赛。我的数据模型与 Combine
相关,不确定这是否与为什么我在 WidgetKit
的 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
(无数据更改)
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
中执行完成处理程序后,不再执行任何代码。
要在小部件上显示数据,您需要在 getTimeline
中获取数据,创建一个从头开始显示数据的视图,然后 return 在完成处理程序中输入该条目。
在您的最后一个示例中,我建议您在 model.fetchSchedule
的完成处理程序中创建您的条目,并将 schedule
对象传递给您的视图。