but I have noticed that my bridge variable is nil whenever I call on it from another method. I believe this is because the bridge is only set when calling on a bridged method from javascript. I have tried everything from creating delegate to create a SingleTon class. None of the above work and I cannot figure out why it is only available in the method that I called from Javascript. Here is my class
Helper.h
#import "RCTBridge.h"
#import "AppDelegate.h"
#import "RCTEventEmitter.h"
@interface Helper : RCTEventEmitter <RCTBridgeModule>
-(void) auth;
@end
Here is my .m file: Helper.m
#import "AppDelegate.h"
#import "Helper.h"
#import "RCTBridge.h"
#import "RCTEventDispatcher.h"
@implementation Helper
RCT_EXPORT_MODULE();
@synthesize bridge = _bridge;
- (NSArray<NSString *> *)supportedEvents {
return @[@"SpotifyHelper"];
}
RCT_EXPORT_METHOD(auth)
{
[self.bridge.eventDispatcher sendDeviceEventWithName:@"SpotifyHelper" body:@{@"Login": @true}];
printf("Auth");
}
RCT_EXPORT_METHOD(play:(NSString *) uri first: id)
{
AppDelegate *appDelegate = [[AppDelegate alloc] init];
[appDelegate play:uri second:id];
}
@end
I call on that method from inside of my delegate like this:
[[AppDelegate alloc] init] auth]
Which is the reason I believe it is not initialized. I'm not sure how to get the RCTBridge variable to not be nil. Any help?
The problem is here:
[[AppDelegate alloc] init] auth]
When you used the macro RCT_EXPORT_MODULE()
React-Native will instantiate the class for you, and any subsequent alloc/init
s will create new instances, unrelated the original. The bridge will not be instantiated in these new instances.
You can solve your problem by using NSNotifications.
Helper.h:
#import "RCTEventEmitter.h"
@interface Helper : RCTEventEmitter
+ (void)emitEventWithName:(NSString *)name andPayload:(NSDictionary *)payload;
@end
Helper.m:
#import "Helper.h"
@implementation Helper
RCT_EXPORT_MODULE();
- (NSArray<NSString *> *)supportedEvents {
return @[@"SpotifyHelper"];
}
- (void)startObserving
{
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(emitEventInternal:)
name:@"event-emitted"
object:nil];
}
- (void)stopObserving
{
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
- (void)emitEventInternal:(NSNotification *)notification
{
[self sendEventWithName:@"SpotifyHelper"
body:notification.userInfo];
}
+ (void)emitEventWithName:(NSString *)name andPayload:(NSDictionary *)payload
{
[[NSNotificationCenter defaultCenter] postNotificationName:@"event-emitted"
object:self
userInfo:payload];
}
// Remaining methods
@end
There is a long discussion thread here: What is the method can be used to send an event from native module to JS
Just to add onto oar.garuna's answer (which was just a complete life saver), for those who have more than one event and want to handle that, the following code will setup a single observer that we can then make a static call to emitEventWithName
and the helper will handle it appropriately and send that event out.
eventHelper.h
@interface eventHelper : RCTEventEmitter
+ (void)emitEventWithName:(NSString *)name andPayload:(NSDictionary *)payload;
@end
eventHelper.m
@implementation eventHelper
RCT_EXPORT_MODULE();
// The list of available events
- (NSArray<NSString *> *)supportedEvents {
return @[@"EventLoggedOut"];
}
// This function listens for the events we want to send out and will then pass the
// payload over to the emitEventInternal function for sending to Javascript
- (void)startObserving
{
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(emitEventInternal:)
name:@"event-emitted"
object:nil];
}
// This will stop listening if we require it
- (void)stopObserving
{
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
// This will actually throw the event out to our Javascript
- (void)emitEventInternal:(NSNotification *)notification
{
// We will receive the dictionary here - we now need to extract the name
// and payload and throw the event
NSArray *eventDetails = [notification.userInfo valueForKey:@"detail"];
NSString *eventName = [eventDetails objectAtIndex:0];
NSDictionary *eventData = [eventDetails objectAtIndex:1];
[self sendEventWithName:eventName
body:eventData];
}
// This is our static function that we call from our code
+ (void)emitEventWithName:(NSString *)name andPayload:(NSDictionary *)payload
{
// userInfo requires a dictionary so we wrap out name and payload into an array and stick
// that into the dictionary with a key of 'detail'
NSDictionary *eventDetail = @{@"detail":@[name,payload]};
[[NSNotificationCenter defaultCenter] postNotificationName:@"event-emitted"
object:self
userInfo:eventDetail];
}
@end
Once that part has been setup you should then be able to make a call to our static function emitEventWithName
from wherever as follows:
[eventHelper emitEventWithName:@"myEventName" andPayload:@{@"key":@"value1"}];
Hope that helps someone!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With