在本机ios中侦听事件

问题描述 投票:8回答:5

我不能为我的生活得到一个事件,从iOS本机跨桥到适当的原生JS上下文正确发送。在Objective-C方面,我希望有一个模块可以轻松地在整个桥上发送事件。我已经调用了这个类EventEmitter,它的定义如下:

// EventEmitter.h

#import "RCTBridge.h"
#import "RCTEventDispatcher.h"

@interface EventEmitter : NSObject<RCTBridgeModule>

  - (void)emitEvent:(NSString *) eventName withData:(id) eventData;

@end

和实施:

// 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

我正在使用sendDeviceEvent和sendAppEvent,因为我无法工作。

在JS方面,我注册在我的一个模块的全局命名空间中接收这些事件(这样我就知道事件订阅将在事件发出之前发生)。我这样注册:

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

在我的日志语句中,我得到以下内容:

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]

所以我可以告诉我发送了一个应用程序事件和一个带有标签blah的设备事件,我已注册用DeviceEventEmitter和NativeAppEventEmitters监听blah事件,但我没有在监听器中回调。

我究竟做错了什么??谢谢阅读!

ios react-native
5个回答
4
投票

我已经尝试调度事件,当你使用bridge手动创建新的EventEmitter实例时,似乎没有初始化[EventEmitter alloc] init]

你应该让react-native创建实例。我检查了原生组件,他们正在使用-(void)setBridge:(RCTBridge *)bridge方法进行初始化工作。请查看RCTLinkingManager以查看示例。它使用NSNotificationCenter来处理事件。

// 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;
}

5
投票

你可以使用NativeEventEmitter

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

在Objective C中,您可以创建

    #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"];

我编写了示例示例来处理从react-native到objectivec和对面的事件。 https://github.com/lengocgiang/event-listener希望这个帮助!!


2
投票

在我的例子中,我通过保持RCTRootView的桥接值并将其传递给发射器实例来实现此功能。

@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];
}

在我的发射器类中:

#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

0
投票

RNNotification * notification = [RNNotification allocWithZone:nil]; [通知sendNotificationToReactNative]我尝试了以上所有内容,但无法在我的应用中使其工作。

最后this为我工作。

#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"}];
}

并在启动功能时

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

0
投票

你必须像这样使用你的发射器类

[[self.bridge moduleForClass:[RNNotification class]] sendNotificationToReactNative];
© www.soinside.com 2019 - 2024. All rights reserved.