1

I cannot make a react-native app push new controllers from an iOS native framework. I'm trying to wrap it up into a react-native library, and I managed to make the base view be displayed, but when I interact with it, new screens won't be pushed. Is it possible to navigate between native screens located into the native framework?

I wrapped the framework into a react-native library successfully, using react-native-create-library. I am able to display the base view, and when clicking on buttons that present views on the same screen (such a datepicker) it works fine. But when I click on a button that should pushes a new view controller, it won't react.

I'm testing it into a dummy brand-new react-native app, and changed the AppDelegate.m to use a UINaVigationController instead of the default UIViewController, as follows:

UIViewController *rootViewController = [UIViewController new];
UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:rootViewController];

[[RNHellLib sharedInstance] configureSDK: navigationController];

Then in my library I'm doing this:

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

RCT_EXPORT_MODULE(RNSearchBox)
RCT_EXPORT_VIEW_PROPERTY(rootController, UIViewController)

SearchBox *mySearchBox;

- (UIView *)view {
    return mySearchBox;
}

+ (instancetype)sharedInstance {
    static RNHellLib *sharedInstance = nil;
    static dispatch_once_t onceToken = 0;
    dispatch_once(&onceToken, ^{
        sharedInstance = [[RNHellLib alloc] init];

    });
    return sharedInstance;
}

- (void) configureSDK: (UINavigationController *)rootController {
    mySearchBox = [[SearchBox alloc] init];
    mySearchBox.rootController = rootController;
}

On the SDK side, I'm pushing new view controllers using viewController.show(viewControllerToBePushed, sender), and also tried with viewController.present(viewControllerToBePushed, animation: true), but screens don't change either way.

I've read tones of docs and tutorials that use react-navigation or similar libraries to navigate between react-native screens, and also between existing (and known) swift views built up into the same app. But this means that the reat-native side has to know in advance the views that we display when interacting with the elements, instead of letting the framework work as a "black-box" on it's own.

Is it possible? Can it work as a "black-box" as does work in other native apps? Or I will need to compulsorily expose all view controllers and trigger them manually from JSX?

toni_piu
  • 135
  • 3
  • 11

1 Answers1

0

I haven't implemented it by myself but it works fine for me in the following library https://github.com/troublediehard/react-native-braintree-xplat

shortly

// RCTBraintree.h

@interface RCTBraintree : UIViewController <RCTBridgeModule, ...>

@property (nonatomic, strong) UIViewController *reactRoot;
...

@end


//  RCTBraintree.m

#import "RCTBraintree.h"

@implementation RCTBraintree

...


RCT_EXPORT_METHOD(showApplePayViewController:(NSDictionary *)options callback:(RCTResponseSenderBlock)callback)
{
    dispatch_async(dispatch_get_main_queue(), ^{
        ...

        PKPaymentAuthorizationViewController *viewController = [[PKPaymentAuthorizationViewController alloc] initWithPaymentRequest:paymentRequest];
        viewController.delegate = self;

        [self.reactRoot presentViewController:viewController animated:YES completion:nil];
    });
}

...

- (UIViewController*)reactRoot {
    UIViewController *root  = [UIApplication sharedApplication].keyWindow.rootViewController;
    UIViewController *maybeModal = root.presentedViewController;

    UIViewController *modalRoot = root;

    if (maybeModal != nil) {
        modalRoot = maybeModal;
    }

    return modalRoot;
}

...

@end
Dima Portenko
  • 3,443
  • 5
  • 35
  • 48
  • So indeed, what you are doing is pushing directly the views from react-native side. This means that I need to make every controller publicly visible, and manage the app flow from react-native as you show me above, isn't it? – toni_piu Aug 19 '19 at 11:07
  • @toni_piu sorry, I don't get you. What do you mean by `react-native side`? React javascript side or native objective-c code? – Dima Portenko Aug 19 '19 at 11:11
  • @toni_piu `[self.reactRoot presentViewController:viewController animated:YES completion:nil];` make new viewController appear, and it isn't necessary should be visible on the React (JavaScript) side. – Dima Portenko Aug 19 '19 at 11:17
  • Hi @dmitri-portenko, I'm sorry I didn't explain myself. I think the problem is the binary framework I'm trying to pull from, originally written in Swift. In the example above, PKPaymentAuthorizationViewController has to be exposed publicly, so that it can be accessed from the react-native lib. So I reformule the question: Can I deal with my viewControllers located at a binary framework if they are properly publicly exposed? Or I need to add the framework's source code directly to Objective-C's library (as Braintree does)? – toni_piu Aug 19 '19 at 12:47
  • 1
    `Can I deal with my viewControllers located at a binary framework if they are properly publicly exposed?` I'm sure you can. – Dima Portenko Aug 19 '19 at 12:51
  • @toni_piu can you please accept the answer if it helps you – Dima Portenko Aug 22 '19 at 13:16