Interact with Home screen widget extension in iOS from React Native(JS)[Part 1]
Introduction
A sample project demonstrating how to interact with the home screen widget extension, introduced in iOS 14, from the Javascript realm in a React Native application.
In the 1st part, we shall create a widget extension in our sample RN app, and write a native module(bridge) to pass data from JS to Swift. Then in the 2nd part, shall see how to utilise the data to configure the widget and dynamically set contents. Finally in the 3rd part, we will see how to update the added widgets periodically and from the App.
We have our sample “WeatherApp” created using react native(v0.63.3), and Xcode(12.0) which allows us to build widget extension.
Add Widget Extension
Open the WeatherApp in Xcode and Choose File > New > Target.
Search for “widget”, will find “Widget Extension” under Application Extension, select that and click next.
Let’s name the target “WeatherWidget”. Also make sure the checkbox next to “Include Configuration Intent” is selected.
(This creates an ‘intentdefinition’ file) In layman’s term this means if we would like to open up a configure screen, by long pressing the widget or home screen, and choosing edit widget option.(of course we want to, more about it later)
Hit finish, and if you see a pop up asking to activate extension scheme, select “Activate”.
Yay! we have added a home screen widget extension for our weather app. Build the app and we can see our app name(WeatherApp) under the widgets list.
Troubleshooting!
If anyone encounter the following error while building the app,
follow this,
In the Xcode project navigator select the “WeatherApp”, under the targets choose “WeatherWidetExtension”, and search for “library search path” inside the “Build Settings”.
Double click on it and if you find “$(TOOLCHAIN_DIR)/usr/lib/swift-5/$(PLATFORM_NAME)” replace it with “$(TOOLCHAIN_DIR)/usr/lib/swift-5.2/$(PLATFORM_NAME)”.
Should roughly look like this after change
Write Native Module/Bridge
Let us create a “Swift file” inside “WeatherApp” group and set the name “WeatherWidgetModule”, make sure under the targets both “WeatherApp” and “WeatherWidgetExtension” are selected.
Xcode will ask if we would like to create a bridging header, go ahead and click “Create Bridging Header”, this will allows us to access the methods that we are about to write in swift file, inside objective c files.
Inside the ‘WeatherWidgetModule.swift’ file let us add our native module and method:
import Foundation@objc(WeatherWidgetModule)class WeatherWidgetModule: NSObject {@objc(setWidgetData:)func setWidgetData(widgetData: NSArray) -> Void {
}}
Now, from the JS part we can pass data to the widget’s side, using the above method
useEffect(() => {WeatherWidgetModule.setWidgetData(data);}, []);
In the next part we shall see how to utilise this data and configure our widget to show some dummy weather information.
Full code here