Share data between React Native and iOS widgets
Having access to app's data in your widget extension is a basic need and how do it is pretty straight up.
iOS widgets are incorporated in the iOS apps, they are in something called app extensions. These app extensions have their own app id, provisioning profile and code sign certificate.
After you created your new widget extension is time to setup a way to share data between widget and the iOS app.
To do this we will activate for both Widget and iOS app something called AppGroup capability. This will allow us to share the data written in UserDefaults.
There a bit of setup work involved here:
- You need to make sure that you have an App Id registered. Go here to see how to create a new App Id.
- You need to have an AppGroup Id registered. Go here to see how to register an AppGroup Id.
- The last step is to assign the AppGroup Id to your App. Go here to see how to link the AppGroup Id.
The same process of creating a new App Id and assigning the AppGroup Id needs to be done also for the Widget Extension.
This is how you initialise the UserDefaults object to be able to read and write data in a such a way that it can used by any app extension that has your newly created AppGroup Id.
class SharedStorageManager {
let APP_GROUP_SHARED_STORAGE_KEY = Bundle.main.infoDictionary?["AppGroupId"] as? String ?? ""
//
// Make it simpler, use this.
// let APP_GROUP_SHARED_STORAGE_KEY = "group.pro.cristiangutu.mysports"
//
func loadDataFromSharedStorage(key: SharedStorageKeys) -> [String: Any] {
let sharedDefaults = UserDefaults.init(suiteName: APP_GROUP_SHARED_STORAGE_KEY)
guard
let jsonStringValue = sharedDefaults?.value(forKey: key.rawValue) as? String,
let data = jsonStringValue.data(using: .utf8)
else { return [:] }
if let jsonDictionary = try? JSONSerialization.jsonObject(with: data, options: []) as? [String: Any] {
return jsonDictionary
} else {
return [:]
}
}
}
This line is important:
UserDefaults.init(suiteName: APP_GROUP_SHARED_STORAGE_KEY)
The suiteName
param must have the AppGroup Id value, group.pro.cristiangutu.mysports
We save the data as a JSON string because it's more convenient to be written from React Native side.
On the React Native side we use react-native-shared-group-preferences to do the job.
import SharedGroupPreferences from 'react-native-shared-group-preferences';
const appGroupIdentifier = 'group.pro.cristiangutu.mysports';
export const saveDataToSharedStorage = async (key: string, data: any) => {
try {
await SharedGroupPreferences.setItem(key, data, appGroupIdentifier);
} catch (errorCode) {
// errorCode 0 = There is no suite with that name.
console.log(errorCode);
}
};
export const loadDataFromSharedStorage = async (key: string) => {
try {
const loadedData = await SharedGroupPreferences.getItem(
key,
appGroupIdentifier
);
return loadedData;
} catch (errorCode) {
// errorCode 0 = no group name exists
// errorCode 1 = there is no value for that key
return null;
}
};
Congratulations! Fom here you can start writing data to your widget exentension.