Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I present a native UIViewController in React Native? (Can't use just a UIView)

Tags:

I'm trying to use ABNewPersonViewController in my React Native app. This is how it's used in Objective-C:

ABNewPersonViewController *picker = [[ABNewPersonViewController alloc] init]; picker.newPersonViewDelegate = self;  UINavigationController *navigation = [[UINavigationController alloc] initWithRootViewController:picker]; [self presentViewController:navigation animated:NO completion:nil]; 

How would I do this in React Native? I can't write a bridged UI component since it's a UIViewController, not a UIView.

Please don't tell me to reimplement it 😟

like image 315
Mark Estefanos Avatar asked Apr 12 '16 01:04

Mark Estefanos


2 Answers

Here's what ended up working for me.

CreateContact.h:

#import <Foundation/Foundation.h> #import <UIKit/UIKit.h> #import <AddressBook/AddressBook.h> #import <AddressBookUI/AddressBookUI.h> #import "RCTBridgeModule.h"  @interface CreateContact : NSObject <ABNewPersonViewControllerDelegate, RCTBridgeModule>  @end 

CreateContact.m:

#import "CreateContact.h" #import "AppDelegate.h"  @implementation CreateContact  RCT_EXPORT_MODULE(CreateContact);   RCT_EXPORT_METHOD(presentContact) {      dispatch_async(dispatch_get_main_queue(), ^{         ABNewPersonViewController *picker = [[ABNewPersonViewController alloc] init];         picker.newPersonViewDelegate = self;         UINavigationController* contactNavigator = [[UINavigationController alloc] initWithRootViewController:picker];         AppDelegate *delegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];         [delegate.window.rootViewController presentViewController:contactNavigator animated:NO completion:nil];     }); }  - (void)newPersonViewController:(ABNewPersonViewController *)newPersonViewController didCompleteWithNewPerson:(ABRecordRef)person {     [newPersonViewController dismissViewControllerAnimated:YES completion:nil]; } @end 

This tutorial has more detail: http://moduscreate.com/leverage-existing-ios-views-react-native-app/

I'll update as I implement the best way to communicate information back to RN.

like image 86
Mark Estefanos Avatar answered Sep 22 '22 04:09

Mark Estefanos


You want to implement a bridged UI component that mounts an empty UIView and is responsible primarily for presenting your UIViewController. The simplest example of this technique is in RCTModalHostView; check out the source code.

Notably, React Native defines a category on UIView that adds a property called reactViewController which climbs the view hierarchy to find the closest UIViewController. Use this UIViewController to present your custom view controller:

- (void)didMoveToWindow {   [super didMoveToWindow];    if (!_isPresented && self.window) {     [self.reactViewController presentViewController:_customViewController                                            animated:NO                                          completion:nil];     _isPresented = YES;   } } 
like image 25
ide Avatar answered Sep 21 '22 04:09

ide