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