Interact with Home screen widget extension in iOS from React Native(JS)[Part 2]
In part 1 we have passed some data from JS to the Swift(Native) side, using a bridge. Now let us cache this data using swift and use that data to configure the widgets.
Sample Data
Our ultimate goal is to use the above data, to configure our widget, using an “Intents extension”, which we will create shortly. We now have the data inside our native module “WeatherWidgetModule”.
Let us split this part into 4 sections:
- Editing the Custom Intent to show a List (the data for the list in Section 4).
- Adding an Intents extension (which is required to pass data to the List created in Section 1).
- Cache data which is at the native module (in a way that it is accessible to all the targets).
- Finally connect sections 3 > 2 > 1 (we can use the cached data and make a list and pass to the List created in Section 1).
1. Edit Custom Intent(Configure screen)
Widget configure screen(Intent) is nothing but the screen that opens up when user long press a widget and choose to edit it, in that screen we can provide the user with some options(list, enum, string etc), which determines that particular widget’s behaviour.
Now in our case we will show a list of weather data providers, user can choose any, and the humidity value from that provider will be displayed on that widget.
let us edit our “WeatherWidget.intentdefinition” file to show the list of providers. This is how the indent file looks by default.
Make sure Category is set as “View” and “Intent is eligible for widgets” checkbox is selected.
Now click on “+” icon in the Parameters section and add new parameter “provider”, click on “Type” and select “Add Type” to create a custom type, upon selecting, a new type with default name will be created, update the name as “ProvidersList”, and select the check boxes “User can edit value…” and “Options are provided dynamically”.
The newly added type must have default properties “identifier” and “displayString” of type string, that is all we need for now.
Now on building the app, we can see that our widget configure screen shows the option that we just created.
Next step is to supply the providers list data to the option. To pass data dynamically to an intent we need another extension called “Intents extension”.
2. Add Intents Extension
Choose File > New > Target and choose the Intents extension and click next.
Set the name as “WeatherWidgetIntentExtension” also set Starting Point to “None”.
Now select the “WeatherWidget.intentdefinition” in the project navigator and on the right hand side, under “Target membership” make sure “WeatherWidgetIntentExtension” is checked.
Select the “WeatherWidgetIntentExtension” from targets list, choose the “General” tab and add “ConfigurationIntent” among supported intents.
Now we can extend the “IntentHandler” to provide dynamic list data. To do so update the file “IntentHandler.swift” with the code below.
extension IntentHandler: ConfigurationIntentHandling {func provideProviderOptionsCollection(for intent: ConfigurationIntent, with completion: @escaping (INObjectCollection<ProvidersList>?, Error?) -> Void) {let list: INObjectCollection<ProvidersList>? = INObjectCollection(items: [])completion(list, nil)}}
3. Cache the data
We could cache the received data using any mechanism of our choice, SQLite, Core Data or any other, for this example we shall simply write it into a json file. What ever the storage mechanism be, the important things is the data being accessible to all the targets (Main app, WeatherWidgetExtension and WeatherWidgetIntentExtension).
To be able to share the file across all the targets, let us add new capability, “App Groups” for the project. Under “Signing and Capabilities” for the target “WeatherApp”, press “+” icon and select “App Groups”, name the group as “group.weather.app”.
Do the same for the targets “WeatherWidgetExtension” and “WeatherWidgetIntentExtension”.
Now we shall update the “WeatherWidgetModule”, to write and read data to/from the json file.
4. connect sections 3 > 2 > 1
Time to connect all 3 sections above! Edit “provideProviderOptionsCollection” method in the “IntentHandler.swift” extension, to read the data from “widgetData.json”, prepare a list and pass data to the “ProvidersList”.
here is our intent(configure screen) now:
Final touch, let us edit the “WeatherWidget.swift” to show the data from the selected provider.
Tada! Here is our widget now!!
There we go :) We will see how to update the widgets, also explore some options and customisations in the next part!
Full code here.