New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Is it possible to push an existing native UIViewController to React-Native's navigator stack #1148

Closed
oceantang opened this Issue May 5, 2015 · 9 comments

Comments

Projects
None yet
10 participants
@oceantang
Copy link

oceantang commented May 5, 2015

hi~
i am beginner at react native.
i want to push an existing native UIViewController with js bridge, but it's not works well.
does any one knows how to do?

@ide

This comment has been minimized.

Copy link
Collaborator

ide commented May 5, 2015

The short answer is no, the NavigatorIOS component doesn't support that. One solution is to separate the view code from the view controller, follow the React Native documentation that shows how to create a JS class for your new native view class, and then display that directly. But... you lose a lot of your view controller logic that way, so you could try embedding the view controller in a view, and then bridging that to JS, but you have to set up view controller containment in a fragile way. Basically it's possible but you're on your own. For RN it's really much better to rewrite with React.

@yelled3

This comment has been minimized.

Copy link
Contributor

yelled3 commented May 14, 2015

@oceantang I also wanted to something similar, but ended up just replacing the rootViewController

#import "AppDelegate.h"
#import "RCTRootView.h"

@interface AppDelegate()

// keep a reference to the React Native VC
@property (nonatomic, strong) UIViewController *reactNativeViewController;

@end


@implementation AppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
  NSURL *jsCodeLocation;

  jsCodeLocation = [NSURL URLWithString:@"http://localhost:8081/index.ios.bundle"];

  RCTRootView *rootView = [[RCTRootView alloc] initWithBundleURL:jsCodeLocation
                                                      moduleName:@"CrowdTest"
                                                   launchOptions:launchOptions];

  self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];

  // keep a reference to the React Native VC
  self.reactNativeViewController = [[UIViewController alloc] init];
  self.reactNativeViewController.view = rootView;

  self.window.rootViewController = self.reactNativeViewController;
  [self.window makeKeyAndVisible];

  return YES;
}


- (void)goToReactNative {

  [self.window.rootViewController dismissViewControllerAnimated:TRUE completion:nil];

}

- (void)goNativeStoryboard {

  UIViewController *vc = [UIStoryboard storyboardWithName:@"NativeStoryboard" bundle:nil].instantiateInitialViewController;

  [self.window.rootViewController presentViewController:vc animated:true completion:nil];

}
@end

call the bridge method SwiftApp.goToNative() from ReactNative js

@objc(SwiftApp)
class SwiftApp: NSObject {
  @objc func goToNative() -> Void {
    if let appDelegate = UIApplication.sharedApplication().delegate as? AppDelegate {
      appDelegate.goNativeStoryboard()
    }
  }

and to go back to ReactNative

import UIKit

class NativeViewController: UIViewController {

    @IBAction func onClick(sender: AnyObject) {
      if let appDelegate = UIApplication.sharedApplication().delegate as? AppDelegate {
        appDelegate.goToReactNative()
      }
    }

}

this is somewhat hacky, but allows you to work directly with native iOS components which aren't yet fully supported.

hope it helps

@brentvatne

This comment has been minimized.

Copy link
Collaborator

brentvatne commented May 30, 2015

Neat solution there @yelled3 😄

As far as I know, this isn't in the roadmap cc @ericvicenti correct me if I am wrong and I will reopen.

@brentvatne brentvatne closed this May 30, 2015

@talkol

This comment has been minimized.

Copy link
Contributor

talkol commented Feb 29, 2016

We're working on something similar to achieve native navigation in iOS, it should be relatively easy to extend for any type of view controller:

https://github.com/wix/react-native-controllers

@willks

This comment has been minimized.

Copy link

willks commented Jun 3, 2016

@talkol I'm already using react-native-controllers (and react-native-navigation), but this isn't clear nor obvious. I'm trying to push an Imgly controller for image editing - but I still can't see how to register the Native UIViewController with RCCManager so that I can push. Any pointers?

@ramakrishna013

This comment has been minimized.

Copy link

ramakrishna013 commented Sep 22, 2016

@yelled3 Can you explain it a bit clearly plz...

@talkol

This comment has been minimized.

Copy link
Contributor

talkol commented Sep 25, 2016

@willks haha, you're right. If you add the new UIViewController's wrapper code to react-native-controllers itself (by forking it) it should be easy since that's exactly how it works internally. UINavigationController and UITabBarController are wrapped this way, so you have several examples.

But this is a core update, the bigger question is how to wrap a new controller externally with a separate library. This means some plugin system needs to be implemented in react-native-controllers. We have something like this actually.. experimental. You can see an example in this project https://github.com/wix/react-native-wordpress-editor. What you have there is an external UIViewController (by WordPress) that is wrapped as an external library to react-native-controllers that allows pushing it and so forth.

Having said all that.. @DanielZlotin from our team has taken over react-native-navigation and his plan is to deprecate react-native-controllers in the next major version (and merge the code into navigation). So I'm not sure this method will remain available moving forward. It's a good idea to add it as a feature request to react-native-navigation if you think it's important.

@jmc420

This comment has been minimized.

Copy link

jmc420 commented Jul 20, 2017

I have trying to solve this issue using an approach similar to @yelled3 but by creating a UINavigationController in AppDelegate.

https://stackoverflow.com/questions/45197759/react-native-push-rather-than-present-native-ios-view

It almost works but when I restore the RN view after returning from the Native view, the RN keyboard is disabled. Any ideas as to why this might happen?

@jagelooyadav

This comment has been minimized.

Copy link

jagelooyadav commented Jan 2, 2018

Yes this possible you can do by making application window root UINavigationController rather than UIViewController.
You need to make below changes in appDelegate.m
NSURL *jsCodeLocation;

jsCodeLocation = [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index.ios" fallbackResource:nil];

RCTRootView *rootView = [[RCTRootView alloc] initWithBundleURL:jsCodeLocation
moduleName:@"projectName"
initialProperties:nil
launchOptions:launchOptions];
rootView.backgroundColor = [[UIColor alloc] initWithRed:1.0f green:1.0f blue:1.0f alpha:1];

self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
UIViewController *rootViewController = [UIViewController new];
UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:rootViewController];
rootViewController.view = rootView;
self.window.rootViewController = navigationController;
navigationController.navigationBar.hidden = YES;
[self.window makeKeyAndVisible];

then pass call back to native code in any native class and push by below code
dispatch_async(dispatch_get_main_queue(), ^{
AppDelegate app = (AppDelegate)[[UIApplication sharedApplication] delegate];
MYViewController *dd = [[MYViewController alloc]init];

[((UINavigationController*)app.window.rootViewController) pushViewController:dd animated:YES];

});

@facebook facebook locked as resolved and limited conversation to collaborators May 30, 2018

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.