-0.5 C
Monday, January 15, 2024

ios – use TimelineProvider to offer array of Exercises

I am constructing an iOS widget that can show a person’s upcoming exercise for the present day.

The frontend of my app makes use of Angular/Ionic and it presently units the widget knowledge any time a person provides a exercise to their calendar through the use of the capacitor-widgetsbridge-plugin, utilising the sharedUserDefaults desk:

// widget.service.ts
import { WidgetsBridgePlugin } from 'capacitor-widgetsbridge-plugin';

async setWidgetData() {
    this.widgetData = {
        // set widget knowledge right here

    await WidgetsBridgePlugin.setItem({
      key: this.key,
      worth: JSON.stringify(this.widgetData),
      group: this.appGroup

The TimelineProvider units the following person exercise like so:

// appWidget.iOS
func getTimeline(for configuration: ConfigurationIntent, in context: Context, completion: @escaping (Timeline<Entry>) -> ()) {
        var entries: [SimpleEntry] = []
        let sharedDefaults = UserDefaults.init(suiteName: "group.app.title")
        let decoder = JSONDecoder()
        decoder.dateDecodingStrategy = .iso8601

        if let jsonString = sharedDefaults?.string(forKey: "nextWorkout"),
            let jsonData = jsonString.knowledge(utilizing: .utf8),
            let decodedWorkout = attempt? decoder.decode(Exercise.self, from: jsonData) {
            var thumbImage: UIImage?
            let dispatchGroup = DispatchGroup()
            // Use a dispatch group to attend for the picture knowledge to be loaded
            if let thumbUrlString = decodedWorkout.thumbUrl,
               let thumbUrl = URL(string: thumbUrlString) {
                URLSession.shared.dataTask(with: thumbUrl) { knowledge, _, _ in
                    defer { dispatchGroup.depart() }
                    if let knowledge = knowledge {
                        thumbImage = UIImage(knowledge: knowledge)
            } else {
            dispatchGroup.notify(queue: .primary) {
                let entry = SimpleEntry(date: Date(), nextWorkout: decodedWorkout, thumbImage: thumbImage, configuration: configuration)
                let timeline = Timeline(entries: entries, coverage: .atEnd)
        } else {
            // Deal with the case the place there isn't any subsequent exercise knowledge obtainable
            let placeholderEntry = SimpleEntry(date: Date(), nextWorkout: Exercise.noDataFound(), thumbImage: nil, configuration: configuration)
            let timeline = Timeline(entries: [placeholderEntry], coverage: .atEnd)

struct SimpleEntry: TimelineEntry {
    let date: Date
    let nextWorkout: Exercise
    let thumbImage: UIImage?
    let configuration: ConfigurationIntent

struct Exercise: Codable {
    let title: String
    let date: Date
    let time: String?
    let thumbUrl: String?

The issue with that is that if a person would not full their exercise for a given day, Monday for instance, there may be nothing in place to set the widget knowledge for the next day when the present one passes (i.e. Monday’s knowledge will nonetheless be proven on Tuesday if a person hasn’t accomplished their exercise).

I need to have the ability to go an array of timeline entries containing the person’s exercises for the complete week forward. I am comparatively new to Swift and Widget growth so issues have not fairly clicked in my head but.

Up to now, I’ve created a further key within the sharedUserDefaults desk on the frontend known as upcomingWorkouts which incorporates an array of scheduled exercises (excluding at the moment’s exercise). The nextWorkout key within the sharedUserDefaults desk simply incorporates the present day exercise. I am having hassle determining the place to go from right here.

Any perception on how finest to implement the specified behaviour could be unbelievable.

Latest news
Related news


Please enter your comment!
Please enter your name here