1

I want my Widget to update for example every 5 seconds. I don't know why it is not working. The code should be right.

Updated Code:

func getTimeline(for configuration: ConfigurationIntent, in context: Context, completion: @escaping (Timeline<Entry>) -> ()) {
        var entries: [SimpleEntry] = []
        
        let currentDate = Date()
        for _ in 0 ..< 5 {
            let entryDate = Calendar.current.date(byAdding: .minute, value: 60, to: currentDate)!
            let entry = SimpleEntry(date: entryDate, configuration: configuration, clubname: networkManager.clubName)
            entries.append(entry)
        }
        
        let timeline = Timeline(entries: entries, policy: .atEnd)
        completion(timeline)
    }
pawello2222
  • 46,897
  • 22
  • 145
  • 209
submariner
  • 308
  • 1
  • 5
  • 23
  • This should be helpful https://stackoverflow.com/questions/64086234/render-images-on-ios-14-widgets. – Asperi Sep 30 '20 at 15:45
  • You mean I need to add a for loop? – submariner Sep 30 '20 at 15:59
  • 1
    If you want to update a Widget every 5 seconds you need to create entries in advance. It's not possible to refresh the timeline so often. Here is a possible example: [Updating time text label each minute in WidgetKit](https://stackoverflow.com/q/64053733/8697793) – pawello2222 Sep 30 '20 at 18:42
  • Can you check the updated code please? – submariner Oct 01 '20 at 07:40
  • @submariner But what do you want to display in every entry? – pawello2222 Oct 01 '20 at 15:35
  • My widget shows some json data. This json data should be updatet for every let's say hour. clubname: networkManager.clubName is what should be updated. – submariner Oct 01 '20 at 15:53
  • My answer to one of your previous questions is applicable here as well: [How to refresh Widget data?](https://stackoverflow.com/a/63977857/8697793). You just need to set the [`after(_:)`](https://developer.apple.com/documentation/widgetkit/timelinereloadpolicy/after(_:)) policy (instead of `never`) to refresh the timeline *after* some chosen date. – pawello2222 Oct 01 '20 at 20:37

2 Answers2

1

Because you added the same entry. If you change the value like the below example, it will be refreshed.

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()
    let chapter = getChapterWith(level: "1") // it is returned a array.
    for index in 0 ..< chapter.count {
        let entryDate = Calendar.current.date(byAdding: .second, value: index, to: currentDate)!
        let entry = SimpleEntry(date: entryDate, chapter: chapter[index])
        entries.append(entry)
    }

    let timelineDate = Calendar.current.date(byAdding: .second, value: 1, to: Date())!
    let timeline = Timeline<SimpleEntry>(entries: entries, policy: .after(timelineDate))
    completion(timeline)
}

func getChapterWith(level: String) -> [Chapter] {
    return []
}

//Chapter is a struct, it is a variable in SimpleEntry.

struct SimpleEntry: TimelineEntry {
    let date: Date
    let chapter: Chapter
}
Cagatay
  • 392
  • 1
  • 4
  • 9
  • Sagol :) But I get the error couldn't find getChapterWith – submariner Oct 01 '20 at 07:24
  • You can set the chapter variable with a string array. Also, you can change the SimpleEntry object with a string variable. – Cagatay Oct 01 '20 at 09:17
  • I am sorry but I really don't understand what you mean. I don't understand what you are doing with: getChapterWith(level: "1") – submariner Oct 01 '20 at 14:33
  • I updated my answer and added to the example of getChapterWithFunc. getChapterWith is a function return a chapter array that is specific to my project domain. So, I returned the empty array you can customize it. – Cagatay Oct 01 '20 at 19:21
0

You are adding a timeline entry for the same date every time:

let currentDate = Date()  // currentDate = now
for _ in 0 ..< 5 {
    let entryDate = Calendar.current.date(byAdding: .minute, value: 60, to: currentDate)!  // entryDate is ALWAYS currentDate + 60 minutes
    let entry = SimpleEntry(date: entryDate, configuration: configuration, clubname: networkManager.clubName)
    entries.append(entry)
}

Instead, use a var and update that:

var entryDate = Date()
for _ in 0 ..< 5 {
    entryDate = Calendar.current.date(byAdding: .minute, value: 60, to: entryDate)!
    let entry = SimpleEntry(date: entryDate, configuration: configuration, clubname: networkManager.clubName)
    entries.append(entry)
}
Darkpaw
  • 31
  • 4
  • What if we don't use that for loop? the data will just update once? – Ahmadreza Nov 11 '20 at 09:53
  • 1
    That's generally what happens if you don't loop, yes... ¯\_(ツ)_/¯ – Darkpaw Nov 12 '20 at 10:32
  • I can't figure out the logic behind it, because it will be called every time the schedule comes & it can be prepared for the next update then, so what is the rush for planning multiple times? – Ahmadreza Nov 13 '20 at 05:16
  • 1
    The loop above adds five timeline entries so that the widget updates every hour for the next five hours. The timeline is there to allow the widget to update with relevant information at relevant times. It's up to you to decide when the widget completely refreshes its data and creates a new timeline (replacing the old timeline). You should set up a relevant timeline each time the data is refreshed. So, the logic is: data arrives > the timeline is created with that data > new data arrives > timeline is created with that data. – Darkpaw Nov 14 '20 at 09:43