Widget is not auto refreshing

Widget needs to be auto refreshed at 6AM & 6PM every day. I have added the following logic/code based on the widget adding time. But I could not see the widget is auto refreshing at 6AM & 6PM

let calendar = Calendar.current

          let TimeComponentfor6AM = DateComponents(calendar: calendar, hour:6)

          let TimeComponentfor6PM   = DateComponents(calendar: calendar, hour: 18, minute: 00)

          let now = Date()

          let startOfToday = calendar.startOfDay(for: now)

          let startTime    = calendar.date(byAdding: TimeComponentfor6AM, to: startOfToday)!

          let endTime      = calendar.date(byAdding: TimeComponentfor6PM, to: startOfToday)!

        if now < startTime {//if widget adds before 6AM

            if let At6AM = Calendar.current.date(bySettingHour: 6, minute: 0, second: 0, of: Date()) {

                let refreshEntryFor6AM = RecommendedWidgetEntry(date: At6AM, recommedationData: recFeedModel)

                refreshEntries.append(refreshEntryFor6AM)

            }

            if let At6PM = Calendar.current.date(bySettingHour: 18, minute: 0, second: 0, of: Date()) {

                let refreshEntryFor6PM = RecommendedWidgetEntry(date: At6PM, recommedationData: recFeedModel)

                refreshEntries.append(refreshEntryFor6PM)

            }

            return refreshEntries

        }

        else if now < endTime { //if the widget adds before 6PM

            if let At6PM = Calendar.current.date(bySettingHour: 18, minute: 0, second: 0, of: Date()) {

                let refreshEntryFor6PM = RecommendedWidgetEntry(date: At6PM, recommedationData: recFeedModel)

                refreshEntries.append(refreshEntryFor6PM)

            }

            let today = Date()

            if let nextDayDate = Calendar.current.date(byAdding: .day, value: 1, to: today)

            {

                if let At6AM = Calendar.current.date(bySettingHour: 6, minute: 0, second: 0, of: nextDayDate) {

                    let refreshEntryFor6AM = RecommendedWidgetEntry(date: At6AM, recommedationData: recFeedModel)

                    refreshEntries.append(refreshEntryFor6AM)

                }

            }

            return refreshEntries

        }

        else { // if widget added post 6PM

            let today = Date()

            if let nextDayDate = Calendar.current.date(byAdding: .day, value: 1, to: today)

            {

                if let At6AM = Calendar.current.date(bySettingHour: 6, minute: 0, second: 0, of: nextDayDate) {

                    let refreshEntryFor6AM = RecommendedWidgetEntry(date: At6AM, recommedationData: recFeedModel)

                    refreshEntries.append(refreshEntryFor6AM)

                }

                if let At6PM = Calendar.current.date(bySettingHour: 18, minute: 0, second: 0, of: nextDayDate) {

                    let refreshEntryFor6PM = RecommendedWidgetEntry(date: At6PM, recommedationData: recFeedModel)

                    refreshEntries.append(refreshEntryFor6PM)

                }

            }

Kindly help me on it if anything missed or need to be added

Replies

Does your code (please use the "Code Block" button in the box on these forums to put your code in a code block) actually add the timeline entries? It's not in your shared code.

The widget timeline is a set of timeline entries which tell the widget to display different data at different times. If you need the widget to be refreshed at 6am and 6pm, you need two entires: one for 6am and one for 6pm. They are not guaranteed to trigger at precisely those times.

You don't need to worry that the user added the widget before or after 6am or 6pm; you just need to add the timeline entries because the system won't try and display data from a point in the past.

So, if the user added the widget at noon, it won't care about the 6am timeline entry because that's in the past.

You need to provide a snapshot of data that applies, and then add your timeline entries.

I would add timeline entries for now, now + 5 minutes, 6pm and 6am, then have the timeline refresh .atEnd.

As you suggested I have added only two timeline entries but still the widget is not getting auto refreshed.

    func getTimeline(in context: Context, completion: @escaping (Timeline<RecommendedWidgetEntry>) -> Void) {

        let accessTokenValue = Keychain.getAccessTokenValue()

        if let token = accessTokenValue, !token.isEmpty  {

               widgetVM.getRecommendedDataForWidget{ (result) in

                    switch result {

                    case .success(let items):

                        widgetVM.downloadImages(recommendedData: items) { (result) in

                            switch result {

                            case .success(_),.failure(_) :

                                var refreshEntries: [RecommendedWidgetEntry] = []

                                if let At6AM = Calendar.current.date(bySettingHour: 6, minute: 0, second: 0, of: Date()) {

                                    let refreshEntryFor6AM = RecommendedWidgetEntry(date: At6AM, recommedationData: items)

                                    refreshEntries.append(refreshEntryFor6AM)

                                }

                                if let At6PM = Calendar.current.date(bySettingHour: 18, minute: 0, second: 0, of: Date()) {

                                    let refreshEntryFor6PM = RecommendedWidgetEntry(date: At6PM, recommedationData: items)

                                    refreshEntries.append(refreshEntryFor6PM)

                                }

                                let timeline = Timeline(entries: refreshEntries, policy: .atEnd)

                                completion(timeline)

                            }

                        }

                    case .failure(_):

                        let entry = RecommendedWidgetEntry(date: Date(), recommedationData: WidgetFeedModel.getPlaceholderData())

                            let timeline = Timeline(entries: [entry], policy: .never)

                            completion(timeline)

                    }

                }

        }

        else {

            if accessTokenValue == nil { // if token is nil then considering it as member is not logged in.

                SharedContentConstants.clearUserDefaultsData()

                let entry = RecommendedWidgetEntry(date: Date(), recommedationData: [])

                let timeline = Timeline(entries: [entry], policy: .never)

                completion(timeline)

                return

            }

        }

    }

On my timeline provider am calling the Rest API to fetch the data to update the widget. Could you please help me out is there any issue with the refresh policy ( My widgets must auto refresh twice a day like 6AM and 6PM)

Kindly provide the reason, why the widgets are not autorefreshing on it's own.

Thanks.

  • Hi Could you please help me out like how to write the entries by referring above code. My widget needs to be refreshed(need to hit the api and show the updated data) twice daily it at 6AM and 6PM.

    Right now am using the policy with .atEND But I could see the same data is rendering at 6AM and 6PM. and the refresh ie API call is happening after 6PM.

    But my requirement is like to hit the api before rendering the widget at 6AM and again needs to hit the api before rendering at 6PM.

Add a Comment

Well, are you sure that the timeline entries are being added? Your code has a few if ... else and switch blocks.

Remove all that cruft and just add those two entries to the timeline, and see if the widget updates. If it doesn't, then there's something wrong with the timeline. If it does, then your issue is with your other code.