简体   繁体   English

当我从另一个方法调用方法时,React-native Bridge为Nil

[英]React-native Bridge is Nil when I call method from another method

but I have noticed that my bridge variable is nil whenever I call on it from another method. 但是我注意到每当我从另一个方法调用它时,我的桥变量都是nil。 I believe this is because the bridge is only set when calling on a bridged method from javascript. 我相信这是因为仅在从javascript调用桥接方法时才设置桥。 I have tried everything from creating delegate to create a SingleTon class. 我已经尝试了从创建委托到创建SingleTon类的所有内容。 None of the above work and I cannot figure out why it is only available in the method that I called from Javascript. 上述工作都没有,我无法弄清楚为什么它仅在我从Javascript调用的方法中可用。 Here is my class 这是我的课

Helper.h 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 这是我的.m文件: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. 我不知道如何让RCTBridge变量不为零。 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. 当您使用宏RCT_EXPORT_MODULE() React-Native将为您实例化该类,并且任何后续的alloc/init将创建与原始实例无关的新实例。 The bridge will not be instantiated in these new instances. 在这些新实例中不会实例化桥。

You can solve your problem by using NSNotifications. 您可以使用NSNotifications解决您的问题。

Helper.h: Helper.h:

#import "RCTEventEmitter.h"

@interface Helper : RCTEventEmitter

+ (void)emitEventWithName:(NSString *)name andPayload:(NSDictionary *)payload;

@end

Helper.m: 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 这里有一个很长的讨论主题: 可以使用什么方法将事件从本机模块发送到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. 只是为了添加到oar.garuna的答案(这只是一个完整的生命保护程序),对于那些有多个事件并想要处理它的人,下面的代码将设置一个观察者,然后我们可以对emitEventWithName进行静态调用并且帮助器将适当地处理它并将该事件发送出去。

eventHelper.h eventHelper.h

@interface eventHelper : RCTEventEmitter

  + (void)emitEventWithName:(NSString *)name andPayload:(NSDictionary *)payload;

@end

eventHelper.m 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: 一旦设置了该部分,您就应该能够从以下任何地方调用我们的静态函数emitEventWithName

[eventHelper emitEventWithName:@"myEventName" andPayload:@{@"key":@"value1"}];

Hope that helps someone! 希望有人帮助!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM