这里是初学者。我正在尝试在小部件中显示来自 JSON API 的数据。在应用程序中加载数据时,代码工作得很好,但是,当我在小部件上使用它时,相同的代码不起作用。我试过 .onAppear 但还是不行。
我的问题几乎与:How do I refresh Widgets in SwiftUI with JSON
它的一个回答说'像这样的异步 API 调用在小部件的视图中不起作用。您应该在时间线提供程序中收集 API 数据。” 正如这个问题所见How to refresh Widget data?
有人可以帮我解释一下吗?我不确定我必须修复什么,因为给定的示例将数据传递到时间线提供程序,而我的则不必。
struct Covid19WidgetView: View {
@State private var covidData2: CovidData2?
@State private var switchView = false
var body : some View {
if #available(iOS 15.0, *) {
Rectangle()
.foregroundColor(Color(red: 88/255, green: 76/255, blue: 244/255))
.overlay{
VStack{
Text("Total cases:")
.foregroundColor(Color.white)
.fontWeight(.semibold)
Text("+ \(covidData2?.Confirmed ?? 0)")
.foregroundColor(Color.white)
.font(.system(size: 20))
.fontWeight(.semibold)
.onAppear{
loadData2()
}
}
}
} else {
// Fallback on earlier versions
}
}
private func loadData2() {
guard let url = URL(string: "https://covid19.th-stat.com/json/covid19v2/getTodayCases.json") else {
return
}
URLSession.shared.dataTask(with: url) { data, response, error in
guard let data = data else {return}
if let decodedData = try? JSONDecoder().decode(CovidData2.self, from: data){
DispatchQueue.main.async {
self.covidData2 = decodedData
}
}
}.resume()
}
}
struct CovidData2: Decodable {
var Confirmed: Int
var Recovered: Int
var Hospitalized: Int
var Deaths: Int
var NewConfirmed: Int
var NewRecovered: Int
var NewDeaths: Int
var UpdateDate: String
}
struct Provider: TimelineProvider {
func placeholder(in context: Context) -> SimpleEntry {
SimpleEntry(date: Date())
}
func getSnapshot(in context: Context, completion: @escaping (SimpleEntry) -> ()) {
let entry = SimpleEntry(date: Date())
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 currentDate = Date()
for hourOffset in 0 ..< 5 {
let entryDate = Calendar.current.date(byAdding: .hour, value: hourOffset, to: currentDate)!
let entry = SimpleEntry(date: entryDate)
entries.append(entry)
}
let timeline = Timeline(entries: entries, policy: .atEnd)
completion(timeline)
}
}
struct SimpleEntry: TimelineEntry {
let date: Date
}
struct Covid19_WidgetEntryView : View {
var entry: Provider.Entry
var body: some View {
Covid19WidgetView()
}
}
@main
struct Covid19_Widget: Widget {
let kind: String = "Covid19_Widget"
var body: some WidgetConfiguration {
StaticConfiguration(
kind: kind,
provider: Provider()
) { entry in
Covid19_WidgetEntryView(entry: entry)
}
.configurationDisplayName("Covid-19 cases Tracker ??")
.description("Display Thailand's new/total number of cases, recovered, and deaths from Covid-19")
.supportedFamilies([.systemSmall])
}
}
struct Covid19_Widget_Previews: PreviewProvider {
static var previews: some View {
Covid19_WidgetEntryView(entry: SimpleEntry(date: Date()))
.previewContext(WidgetPreviewContext(family: .systemSmall))
}
}