我的代码获取了两个JSON
变量,并将其显示在我的窗口 WidgetKit 上。
窗口 WidgetKit 保持空白。没有 WidgetKit ,它向我显示了我的应用程序中所有正确的东西。
我究竟做错了什么?代码中的API仅用于测试,因此您也可以进行检查。
我需要更改使其在 WidgetKit 中显示吗?
我的结构:
import Foundation
struct Results: Decodable {
let data: [Post]
}
struct Post: Decodable, Identifiable {
let id: String
var objectID: String {
return id
}
let home_name: String
let away_name: String
}
撷取JSON:import Foundation
class NetworkManager: ObservableObject {
@Published var posts = [Post]()
@Published var test = ""
@Published var test2 = ""
func fetchData() {
if let url = URL(string: "https://livescore-api.com/api-client/teams/matches.json?number=10&team_id=19&key=I2zBIRH3S01Kf0At&secret=6kLvfRivnqeNKUzsW84F0LISMJC1KdvQ&number=7&team_id=46") {
let session = URLSession(configuration: .default)
let task = session.dataTask(with: url) { (gettingInfo, response, error) in
if error == nil {
let decoder = JSONDecoder()
if let safeData = gettingInfo {
do {
let results = try decoder.decode(Results.self, from: safeData)
DispatchQueue.main.async {
self.posts = results.data
self.test = results.data[0].away_name
self.test2 = results.data[0].home_name
}
} catch {
print(error)
}
}
}
}
task.resume()
}
}
}
显示 WidgetKit :import WidgetKit
import SwiftUI
import Intents
struct Provider: IntentTimelineProvider {
func placeholder(in context: Context) -> SimpleEntry {
SimpleEntry(date: Date(), configuration: ConfigurationIntent())
}
func getSnapshot(for configuration: ConfigurationIntent, in context: Context, completion: @escaping (SimpleEntry) -> ()) {
let entry = SimpleEntry(date: Date(), configuration: configuration)
completion(entry)
}
func getTimeline(for configuration: ConfigurationIntent, 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, configuration: configuration)
entries.append(entry)
}
let timeline = Timeline(entries: entries, policy: .atEnd)
completion(timeline)
}
}
struct SimpleEntry: TimelineEntry {
let date: Date
let configuration: ConfigurationIntent
}
struct WidgetNeuEntryView : View {
@ObservedObject var networkManager = NetworkManager()
var entry: Provider.Entry
var body: some View {
Text(networkManager.test)
}
}
@main
struct WidgetNeu: Widget {
let kind: String = "WidgetNeu"
var body: some WidgetConfiguration {
IntentConfiguration(kind: kind, intent: ConfigurationIntent.self, provider: Provider()) { entry in
WidgetNeuEntryView(entry: entry)
}
.configurationDisplayName("My Widget")
.description("This is an example widget.")
}
}
struct WidgetNeu_Previews: PreviewProvider {
static var previews: some View {
WidgetNeuEntryView(entry: SimpleEntry(date: Date(), configuration: ConfigurationIntent()))
.previewContext(WidgetPreviewContext(family: .systemSmall))
}
}
networkManager.test
应该显示为文本,但是正如我所说的是空白的。 最佳答案
您不能像通常在应用程序中使用的那样使用ObservedObject
。
在窗口 WidgetKit 中,您使用TimelineProvider
为您的 View 创建一个Entry
。
TimelineEntry
中添加另一个属性,我们称它为clubName
:struct SimpleEntry: TimelineEntry {
let date: Date
let clubName: String
}
NetworkManager
并以completion
返回结果:class NetworkManager {
func fetchData(completion: @escaping ([Post]) -> Void) {
...
URLSession(configuration: .default).dataTask(with: url) { data, _, error in
...
let result = try JSONDecoder().decode(Results.self, from: data)
completion(result.data)
...
}
.resume()
}
}
NetworkManager
中使用TimelineProvider
并在fetchData
完成时创建时间线条目:struct Provider: TimelineProvider {
var networkManager = NetworkManager()
func placeholder(in context: Context) -> SimpleEntry {
SimpleEntry(date: Date(), clubName: "Club name")
}
func getSnapshot(in context: Context, completion: @escaping (SimpleEntry) -> Void) {
let entry = SimpleEntry(date: Date(), clubName: "Club name")
completion(entry)
}
func getTimeline(in context: Context, completion: @escaping (Timeline<Entry>) -> Void) {
networkManager.fetchData { posts in
let entries = [
SimpleEntry(date: Date(), clubName: posts[0].home_name)
]
let timeline = Timeline(entries: entries, policy: .never)
completion(timeline)
}
}
}
entry.clubName
:struct WidgetNeuEntryView: View {
var entry: Provider.Entry
var body: some View {
VStack {
Text(entry.date, style: .time)
Text("Club: \(entry.clubName)")
}
}
}
请注意,在上面的示例中,重新加载策略设置为
never
,仅加载一次数据。如果要自动重新加载时间轴,可以轻松将其更改为
atEnd
或after(date:)
。如果您需要随时手动重新加载时间轴,则可以致电:
WidgetCenter.shared.reloadAllTimelines()
这将在App和Widget中都适用。这是一个GitHub repository,带有不同的窗口 WidgetKit 示例,包括网络窗口 WidgetKit 。
关于swift - 如何刷新 WidgetKit 数据?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/63976424/