Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React Native and Objective C delegates

I am quite new to react native and and the bridging mechanism with native code, especially when the framework has delegates. Assume I am trying to bridge the following framework:

@protocol BRPtouchNetworkDelegate;

@class PLNetworkModule;

@interface BRPtouchNetworkManager : NSObject <NSNetServiceBrowserDelegate,NSNetServiceDelegate>


@property(retain, nonatomic) NSMutableArray* registeredPrinterNames;
@property(assign, nonatomic) BOOL isEnableIPv6Search;


- (int)startSearch: (int)searchTime;
- (NSArray*)getPrinterNetInfo;

- (BOOL)setPrinterNames:(NSArray*)strPrinterNames;
- (BOOL)setPrinterName:(NSString*)strPrinterName;

- (id)initWithPrinterNames:(NSArray*)strPrinterNames;
- (id)initWithPrinterName:(NSString*)strPrinterName;

@property (nonatomic, assign) id <BRPtouchNetworkDelegate> delegate;

@end

@protocol BRPtouchNetworkDelegate <NSObject>

-(void) didFinishSearch:(id)sender;

@end

The following is the bridge module I implemented:

RCTBRPtouchNetworkManager.h

#import <React/RCTBridgeModule.h>
#import <BRPtouchPrinterKit/BRPtouchPrinterKit.h>

@interface RCTBRPtouchNetworkManager : NSObject <RCTBridgeModule, BRPtouchNetworkDelegate>
@end

RCTBRPtouchNetworkManager.m

#import "RCTBRPtouchNetworkManager.h"
#import <BRPtouchPrinterKit/BRPtouchPrinterKit.h>
#import <React/RCTLog.h>

@implementation RCTBRPtouchNetworkManager {
  BRPtouchNetworkManager  *_networkManager;
}

RCT_EXPORT_MODULE();

RCT_EXPORT_METHOD(addEvent:(NSString *)name location:(NSString *)location)
{
  RCTLogInfo(@"Pretending to create an event %@ at %@", name, location); //a dummy method to test the bridge
}

RCT_EXPORT_METHOD(startSearchWithTimeout:(int)time) {
  RCTLogInfo(@"Bridge started search with time %d", time);

  _networkManager = [[BRPtouchNetworkManager alloc] init];
  _networkManager.delegate = self; //I'm setting delegate here
  _networkManager.isEnableIPv6Search = NO;
  NSString *  path = [[NSBundle mainBundle] pathForResource:@"PrinterList" ofType:@"plist"];
  if( path )
  {
    NSDictionary *printerDict = [NSDictionary dictionaryWithContentsOfFile:path];
    NSArray *printerList = [[NSArray alloc] initWithArray:printerDict.allKeys];
    [_networkManager setPrinterNames:printerList];
  } else {
    RCTLogInfo(@"PrinterList path not found");
  }

  //  Start printer search
  [_networkManager startSearch: 5.0];

}

- (void)didFinishSearch:(id)sender {
  NSLog(@"didFinishedSearch"); //this delegate method is not called
}

@end

I can easily call the dummy method and see the results in the logs. However, the delegate method didFinishSearch() is never called. I call this from javascript as follows:

componentDidMount() {
    let networkManager = NativeModules.BRPtouchNetworkManager;
    networkManager.startSearchWithTimeout(5.0);
}

I there something I am missing? Am I implementing delegate properly? Is this kind of functionality even possible (can't seem to not since the delegate method was used by iOS community for a long time). Your help is much appreciated.

EDIT

I found that adding the following to my bridge manager file made the delegate to fire (thanks to this post)

- (dispatch_queue_t)methodQueue
{
    return dispatch_get_main_queue();
}

However, even though this solves the problem, I'd like a more technical understanding on what is going on here since I can't seem to exactly grasp it. Thank you

like image 837
jms Avatar asked Jul 02 '18 09:07

jms


People also ask

What is Objective-C delegate?

An Objective-C delegate is an object that has been assigned to the delegate property another object. To create one, you define a class that implements the delegate methods you're interested in, and mark that class as implementing the delegate protocol.

Does React Native still use bridge?

The Bridge in React Native permits the JavaScript code and the Native code to interact with each other. Without the bridge in React Native, there is absolutely no means for the native code to transmit any information to the JavaScript code and vice versa.


1 Answers

I know this isn’t an an answer to the post but for the bit where you’ve asked for a more technical understanding - dispatch_get_main_queue(); puts the delegate method responses on to the main thread. Since JS is single threaded any process on the background thread won’t be visible to it.

like image 122
FlyingKitlets Avatar answered Sep 19 '22 14:09

FlyingKitlets