In this blog post, I will share the code for a simple RCTBridgeModule that can write/read key-value from React Native.
The use case for this is to access the data in iOS Share Extension using value set from React Native.
So that the Share Extension can perform API call with sufficient data that was set in React Native, and thus giving user a much better experience similar to other natively built apps. This is a much more complicated implementation and there are much simpler ways to get it done without writing too many native code and that will be for another blog post.
Let's get back and focus on this topic, get and set value in UserDefaults
that are accesible in Share Extension.
In order to achieve that, we need to use UserDefaults
with suiteName
that starts with group.
.
Before you proceed, please make sure that you have already created Share Extension and updated App Groups
in the Signing & Capabilities
.
This is not covered in this post and there are alot of online resources for this topic.
I'll name it SharedUserDefaults.h
#ifndef SharedUserDefaults_h
#define SharedUserDefaults_h
#endif
#import <Foundation/Foundation.h>
#if __has_include(<React/RCTAssert.h>)
#import <React/RCTBridgeModule.h>
#else
#import "RCTBridgeModule.h"
#endif
@interface SharedUserDefaults : NSObject <RCTBridgeModule>
@end
SharedUserDefaults.m
#import <Foundation/Foundation.h>
#import "SharedUserDefaults.h"
@implementation SharedUserDefaults
RCT_EXPORT_MODULE()
+ (BOOL)requiresMainQueueSetup
{
return YES;
}
RCT_EXPORT_METHOD(set:(NSString *)suiteName
key:(NSString *)keyName
value:(NSString *)value)
{
NSUserDefaults *shareExtensionDefaults = [[NSUserDefaults alloc] initWithSuiteName: suiteName];
[shareExtensionDefaults setObject:value forKey:keyName];
NSLog(@"val written %@", value);
}
RCT_EXPORT_METHOD(get:(NSString *)suiteName
key:(NSString *)keyName
resolver: (RCTPromiseResolveBlock)resolve
rejecter:(RCTPromiseRejectBlock)reject)
{
NSUserDefaults *shareExtensionDefaults = [[NSUserDefaults alloc] initWithSuiteName: suiteName];
NSString *val = [shareExtensionDefaults stringForKey:keyName];
if (val == nil) {
NSError *error = [NSError errorWithDomain:@"org.reactjs.native.example.Bill" code:0 userInfo:@{ @"message": @"Empty" }];
reject(@"error", @"error description", error);
} else {
resolve(val);
}
}
@end
And you can use the methods from the native module you've just written.
In your React Native project, you can now get and set key-value pair to UserDefaults via the native module.
import { NativeModules } from 'react-native';
const SharedUserDefaults = NativeModules.SharedUserDefaults;
// Usage
// Set
SharedUserDefaults.set("group.org.reactjs.native.example.YourProject", "yourKey", "some string to be stored");
// Get
let val = await SharedUserDefaults.get("group.org.reactjs.native.example.YourProject", "yourKey");
In iOS, the value can be retrieved in ShareViewController.swift
or AppDelegate.m
.
Swift
var userDefaults = UserDefaults(suiteName: "group.org.reactjs.native.example.YourProject")
// Get value stored earlier
let storedValue = userDefaults?.object(forKey: "yourKey") as? String
// Set new value
userDefaults?.set("some string to be stored", forKey: "yourKey")
Obj-C
NSUserDefaults *userDefaults = [[NSUserDefaults alloc] initWithSuiteName: @"group.org.reactjs.native.example.YourProject"];
// Get value stored earlier
NSString *val = [userDefaults stringForKey:@"yourKey"];
// Set new value
[userDefaults setObject:@"some string to be stored" forKey:@"yourKey"];
You are now all set!
Now you can set value from React Native and retrieve it in your ShareViewController.swift
.
That's it! Hope it helps.
Cheers.