React Native and Objective C delegates
Asked Answered
V

1

11

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

Vaughnvaught answered 2/7, 2018 at 9:25 Comment(0)
S
3

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.

Swinney answered 11/5, 2021 at 21:13 Comment(3)
Wow. That actually makes sense. If you can confirm that delegates that happen on background threads need to be dispatched to main_thread when using react-native bridges, I can accept this answer.Vaughnvaught
So delegates methods are ran on the thread they are called in. If the code snippet above works, it’s safe to assume that it would be on a background thread. This post has more details: #7881242Swinney
So I have no authoritative proof as such in terms of React Native for this except that I was using a different third party SDK and the code snippet also fixed the delegate methods and allowed me to get the events. I think it’s a reasonable inference given the info I’ve found on the matter and my own experience! Hopefully that’s enough for you to accept my answer haha!Swinney

© 2022 - 2024 — McMap. All rights reserved.