I use WidgetCenter.shared.reloadAllTimelines()
in my main app to refresh my widget.
The widget contains a picture and a String which gets fetched with a json request. If I use the code above the picture gets refreshed immediately. So thats how it should be.
But the string stays the same. It needs to do another json request. But it does not. It shows the old String. Why? The String gets imported with TimelineEntry. So I guess I also need to reload TimelineEntry?
How can I do that? For the String I use in my view entry.clubname
Here is some samplecode. I removed a bit of it so that it is not to much code.
My Networking:
class NetworkManager: ObservableObject {
@Published var clubNameHome = "..."
init() {
fetchData() // fetch data must be called at least once
}
func fetchData() {
if let url = URL(string: "...) {
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.clubNameHome = results.data[0]....
if #available(iOS 14.0, *) {
WidgetCenter.shared.reloadAllTimelines()
} else {
// Fallback on earlier versions
}
}
} catch {
print(error)
}
}
}
}
task.resume()
}
}
}
And my TimelineProvider with View:
struct Provider: IntentTimelineProvider {
let networkManager = NetworkManager()
func placeholder(in context: Context) -> SimpleEntry {
SimpleEntry(date: Date(), configuration: ConfigurationIntent(), clubnamehome: networkManager.clubNameHome)
}
func getSnapshot(for configuration: ConfigurationIntent, in context: Context, completion: @escaping (SimpleEntry) -> ()) {
let entry = SimpleEntry(date: Date(), configuration: configuration, clubnamehome: networkManager.clubNameHome)
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()
let entryDate = Calendar.current.date(byAdding: .minute, value: 15, to: currentDate)!
let entry = SimpleEntry(date: entryDate, configuration: configuration, clubnamehome: networkManager.clubNameHome)
entries.append(entry)
let timeline = Timeline(entries: entries, policy: .atEnd)
completion(timeline)
}
}
struct SimpleEntry: TimelineEntry {
let date: Date
let configuration: ConfigurationIntent
let clubnamehome: String
}
struct MyTeamWidgetEntryView : View {
var entry: Provider.Entry
var body: some View {
HStack {
Spacer()
VStack (alignment: .leading, spacing: 0) {
Spacer().frame(height: 10)
HStack {
Spacer()
switch logo {
case "arminia":
Image("bundesliga1/arminia").resizable().aspectRatio(contentMode: .fit).frame(width: 90, height: 90, alignment: .center)
case "augsburg":
Image("bundesliga1/augsburg").resizable().aspectRatio(contentMode: .fit).frame(width: 90, height: 90, alignment: .center)
default:
Image("bundesliga1/bayern").resizable().aspectRatio(contentMode: .fit).frame(width: 90, height: 90, alignment: .center)
}
}
HStack{
Text(entry.clubname)
}
}
}}}