Neo.Mxn0
Neo.Mxn0

Reputation: 1096

ios 14 widget: How to reload timeline after UserDefaults changed

I have a ios 14 widget that refresh every 5 minutes

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

The entries depends on the configuration on my MainApp.

I use UserDefaults to share data between MainApp and Widget.

@AppStorage("FollowingCatalog", store: UserDefaults(suiteName: "group.vn.f19.com"))
var catalogItemsData: Data = Data()

I've successfully mirrored the widget content base on UserDefaults data. BUT my problem is the my widget refresh the UI only after .atEnd policy, every 5 minutes

That cause a bad UX

How can I refresh widget content immediately right after my configuration in UserDefaults was changed?

Thanks for your supports.

Upvotes: 6

Views: 2981

Answers (3)

Neo.Mxn0
Neo.Mxn0

Reputation: 1096

BTW, if you're using react-native, I've already created a module to support this issue:

react-native-widget-bridge

Upvotes: 1

Neo.Mxn0
Neo.Mxn0

Reputation: 1096

To clarify the whole workflow, I add some note here:

You can call WidgetCenter not only from widget but from your main app.

WidgetCenter.shared.reloadAllTimelines()
WidgetCenter.shared.reloadTimelines(ofKind: "com.myApp.myWidget........")

So the flow is:

  1. User change something on MainApp, eg: I rearrange the stock items in the following list

  2. MainApp save the data to UserDefaults, eg: save the list item order

  3. MainApp trigger reload widget by:

    WidgetCenter.shared.reloadTimelines(ofKind: "mone24h_widget")
    

    You can get the kind by looking into your widget entry file:

    @main
    struct mone24h_widget: Widget {
       let kind: String = "mone24h_widget"
    
  4. Widget will reload the timeline, I will get the shared data from UserDefaults here. Done the work. Eg: Re-render my stocks list base on the arrangement passed from MainApp

Upvotes: 5

rohanphadte
rohanphadte

Reputation: 1018

In Keeping a Widget Up to Date by Apple, to inform your widgets to update its timeline and its content, you call:

WidgetCenter.shared.reloadAllTimelines()

This reloads all widgets that your app has. If you want to reload a specific widget (in the case your app has multiple different widget types), use WidgetCenter.shared.reloadTimelines(ofKind: "com.myApp.myWidget") instead.

Upvotes: 3

Related Questions