I'm creating an app to integrate react-native
with an existing Swift app.
I've looked into similar issues:
While following different tutorials:
And the official docs
The problem is: all of them are outdated (but the docs). Most of them use the legacy Navigation
rather than Stack Navigator
. One of the tutorials (the one with an asterisk) shows how to dismiss the React Native app back to the Native app using the rootTag
of the app, but again, this was done with the legacy Navigation
.
If I try to do the same, I'm not able to see the props
from my app.
I have a single Storyboard with a Button
inside that when clicked calls this UIViewController
:
ButtonController
import Foundation
import UIKit
import React
class ButtonController: UIViewController {
@IBOutlet weak var button: UIButton!
@IBAction func buttonClicked(_ sender: Any) {
let data:[String : String] = ["onNavigationStateChange": "{handleNavigationChange}",
"uriPrefix":"/app"];
let rootView = MixerReactModule.sharedInstance.viewForModule("ReactNativeApp", initialProperties: data)
let viewController = UIViewController()
viewController.view = rootView
self.present(viewController, animated: true, completion: nil)
}
}
And when I start the app I can see this:
2019-10-23 10:29:30.021 [info][tid:com.facebook.react.JavaScript] Running "ReactNativeApp" with {"rootTag":1,"initialProps":{"uriPrefix":"/app","onNavigationStateChange":"{handleNavigationChange}"}}
But when I try to access the this.props
property on React Native code I get undefined
.
index.js
import HomeScreen from './components/HomeScreen'
import {AppRegistry} from 'react-native';
import {createAppContainer} from 'react-navigation';
import {createStackNavigator} from 'react-navigation-stack';
const MainNavigator = createStackNavigator({
Home: {screen: HomeScreen}
}, {
initialRouteName: 'Home'
})
const NavigationApp = createAppContainer(MainNavigator);
AppRegistry.registerComponent('ReactNativeApp', () => NavigationApp)
console.log("NANANA1", this)
console.log("NANANA2", this.routeName)
console.log("NANANA3", MainNavigator)
console.log("NANANA4", MainNavigator.props)
console.log("NANANA5", NavigationApp)
console.log("NANANA6", NavigationApp.props)
export default NavigationApp
HomeScreen.js
import React from 'react';
import {Text, View, Button, NativeModules} from 'react-native';
var RNBridge = NativeModules.RNBridge;
export default class HomeScreen extends React.Component {
static navigationOptions = {
headerTitle: () => (
<Text>'Welcome'</Text>
),
headerLeft: () => (
<Button title="Dismiss" onPress={() => {
console.log("WOLOLO: ", RNBridge)
console.log("ROGAN: ", this._reactInternalFiber.tag)
RNBridge.dismissPresentedViewController(this._reactInternalFiber.tag)
// RNBridge.dismissPresentedViewController(1)
}}/>
)
};
render() {
console.log('KIKIKI', this._reactInternalFiber.tag)
console.log("MMMMMMM: ", this.props)
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>Home Screen</Text>
</View>
);
}
}
These are the 2 files that I use in RN to generate my View. I've tried many things to get the rootTag
value, and the only one that seems to provide this value is (tag
and rootTag
on XCode are the same (1
))
this._reactInternalFiber.tag
But I don't know how to send these values to my headerLeft
method to use the same tag so that when I press the Dismiss
button it calls the Swift code for dismissPresentedViewController
.
How can I dismiss my VC effectively? Or at least get the rootTag
being passed from Swift to my headerLeft()
method?
I'm using these versions of react-native
:
react-native-cli: 2.0.1
react-native: 0.61.2
If your are looking to dismiss the native swift view controller presented from RN View
self.dismiss(animated: true, completion: nil)
I present the swift view controller as below
let modelVC = ModelViewController() <-- sub class of UIViewController
DispatchQueue.main.async {
let navController = UINavigationController(rootViewController: modelVC)
navController.modalPresentationStyle = .fullScreen
let topController = UIApplication.topMostViewController()
topController?.present(navController, animated: true, completion: nil)
}
I have an extension on the UIApplication to find out what is the top most view controller which is used above
extension UIApplication {
class func topMostViewController(controller: UIViewController? = UIApplication.shared.keyWindow?.rootViewController) -> UIViewController? {
if let navigationController = controller as? UINavigationController {
return topMostViewController(controller: navigationController.visibleViewController)
}
if let tabController = controller as? UITabBarController {
if let selected = tabController.selectedViewController {
return topMostViewController(controller: selected)
}
}
if let presented = controller?.presentedViewController {
return topMostViewController(controller: presented)
}
return controller
}
}