Listening for events in real ios

I can’t get an event for my whole life to send correctly from iOS, native across the bridge, to respond to my own JS context. On the Objective-C side, I want to have a module for easily passing events across the bridge. I called this class EventEmitter and its definition is as follows:

// EventEmitter.h #import "RCTBridge.h" #import "RCTEventDispatcher.h" @interface EventEmitter : NSObject<RCTBridgeModule> - (void)emitEvent:(NSString *) eventName withData:(id) eventData; @end 

and implementation:

 // EventEmitter.m #import "EventEmitter.h" @implementation EventEmitter RCT_EXPORT_MODULE(); @synthesize bridge = _bridge; - (void)emitEvent:(NSString *) eventName withData:(id) eventData { NSLog( @"emitting %@ with data %@", eventName, [eventData description] ); [[_bridge eventDispatcher] sendDeviceEventWithName:eventName body:eventData]; [[_bridge eventDispatcher] sendAppEventWithName:eventName body:eventData]; } @end 

I use sendDeviceEvent and sendAppEvent because I cannot get it to work.

On the JS side, the things that I register in order to receive these events in the global namespace of one of my modules (so that I know that subscribing to events will happen before the event occurs). I register like this:

 console.log( 'ADDING EVENT LISTENERS' ); NativeAppEventEmitter.addListener( 'blah', test => console.log( 'TEST1', test ) ); DeviceEventEmitter.addListener( 'blah', test => console.log( 'TEST2', test ) ); 

In my log statements, I get the following:

 2016-03-19 12:26:42.501 [trace][tid:com.facebook.React.JavaScript] ADDING EVENT LISTENERS 2016-03-19 12:26:43.613 [name redacted][348:38737] emitting blah with data [data redacted] 

So, I can say that I send both the application event and the device event with the blah tag, and I registered to listen to the blah event with both DeviceEventEmitter and NativeAppEventEmitters, but I do not get back in the listeners.

What am I doing wrong? Thanks for reading!

+6
source share
4 answers

I tried sending events, and it seems that the bridge not initialized when creating new instances of EventEmitter manually using [EventEmitter alloc] init]

You must allow instance instances with reaction. I checked my own components and they use the -(void)setBridge:(RCTBridge *)bridge method to complete the initialization. Read the RCTLinkingManager to see an example. It uses the NSNotificationCenter to handle events.

 // registering for RCTOpenURLNotification evet when the module is initialised with a bridge - (void)setBridge:(RCTBridge *)bridge { _bridge = bridge; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleOpenURLNotification:) name:RCTOpenURLNotification object:nil]; } // emitting openURL event to javascript - (void)handleOpenURLNotification:(NSNotification *)notification { [_bridge.eventDispatcher sendDeviceEventWithName:@"openURL" body:notification.userInfo]; } // creating RCTOpenURLNotification event to invoke handleOpenURLNotification method + (BOOL)application:(UIApplication *)application openURL:(NSURL *)URL sourceApplication:(NSString *)sourceApplication annotation:(id)annotation { NSDictionary<NSString *, id> *payload = @{@"url": URL.absoluteString}; [[NSNotificationCenter defaultCenter] postNotificationName:RCTOpenURLNotification object:self userInfo:payload]; return YES; } 
+2
source

You can use NativeEventEmitter

 // register eventEmitter const {NGListener} = NativeModules; // NSListener is my class this.eventEmitter = new NativeEventEmitter(NativeModules.NGListener); this.eventEmitter.addListener('CancelEvent', (data) => { console.log(data); }) 

In ObjectiveC you can create

  #import <RCTViewManager.h> #import <RCTEventEmitter.h> @interface NGListener: RCTEventEmitter <RCTBridgeModule> @end @implementation NGListener RCT_EXPORT_MODULE(); - (NSArray<NSString*> *)supportedEvents { return @[@"CancelEvent", @"OKEvent"]; } // And you sent event you want from objectC to react-native [self sendEventWithName:@"CancelEvent" body:@"Tap`enter code here` on Cancel button from Objc"]; 

I wrote a sample example to handle the event from reaction-native to objectivec and vice versa. https://github.com/lengocgiang/event-listener Hope this help!

+3
source

In my case, I got this working by storing the bridge value from RCTRootView and passing it to the emitter instance.

 @implementation AppDelegate { RCTBridge *rootBridge; } - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { NSURL *jsCodeLocation; ...... RCTRootView *rootView = [[RCTRootView alloc] initWithBundleURL:jsCodeLocation moduleName:@"MyApp" initialProperties:nil launchOptions:launchOptions]; rootBridge = rootView.bridge; ....... } - (IBAction)doAction:(id)sender { BridgeEvents *events = [[BridgeEvents alloc] init]; [events setBridge:rootBridge]; [events doMyAction]; } 

In my emitter class:

 #import "RCTEventEmitter.h" @interface BridgeEvents : RCTEventEmitter <RCTBridgeModule> - (void)doMyAction; @end #import "BridgeEvents.h" @implementation BridgeEvents RCT_EXPORT_MODULE(); - (NSArray<NSString *> *)supportedEvents { return @[@"onEvent"]; } - (void)doMyAction { [self sendEventWithName:@"onEvent" body:@""]; } @end 
+1
source

RNNotification * notification = [RNNotification allocWithZone: nil]; [notification sendNotificationToReactNative] I tried everything above and could not get it to work in my application.

Finally this one worked for me.

 #import "RNNotification.h" @implementation RNNotification RCT_EXPORT_MODULE(); + (id)allocWithZone:(NSZone *)zone { static RNNotification *sharedInstance = nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ sharedInstance = [super allocWithZone:zone]; }); return sharedInstance; } - (NSArray<NSString *> *)supportedEvents { return @[@"EventReminder"]; } - (void)sendNotificationToReactNative { [self sendEventWithName:@"EventReminder" body:@{@"name": @"name"}]; } 

and when the function starts

 RNNotification *notification = [RNNotification allocWithZone: nil]; [notification sendNotificationToReactNative] 
0
source

All Articles