Отклонить React Native RCTRootView обратно в Native ViewController - PullRequest
0 голосов
/ 23 октября 2019

Я создаю приложение для интеграции react-native с существующим приложением Swift.

Я рассматривал похожие проблемы:

Покаследующие различные учебные пособия:

И официальные документы

Проблема в том, что все ониустаревшие (но документы). Большинство из них используют устаревшие Navigation, а не Stack Navigator. В одном из учебных пособий (со звездочкой) показано, как закрыть приложение React Native обратно в приложение Native, используя rootTag приложения, но, опять же, это было сделано с помощью устаревшего Navigation.

Если я попытаюсь сделать то же самое, я не смогу увидеть props из моего приложения.

У меня есть одна раскадровка с Button внутри, которая при нажатии вызывает это 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)
    }
}

И когда я запускаю приложение, я вижу это:

2019-10-23 10:29:30.021 [info][tid:com.facebook.react.JavaScript] Running "ReactNativeApp" with {"rootTag":1,"initialProps":{"uriPrefix":"/app","onNavigationStateChange":"{handleNavigationChange}"}}

Но когда я пытаюсь получить доступ кthis.props свойство в React Native code Я получаю 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>
      );
    }
}

Это 2 файла, которые я использую в RN для создания моего просмотра. Я пробовал много вещей, чтобы получить значение rootTag, и единственное, что, кажется, предоставляет это значение (tag и rootTag на XCode одинаковы (1))

this._reactInternalFiber.tag

Но я не знаю, как отправить эти значения в мой метод headerLeft, чтобы использовать тот же тег, чтобы при нажатии кнопки Dismiss он вызывал код Swift для dismissPresentedViewController.

* 1082. * Как я могу эффективно отказаться от моего VC? Или, по крайней мере, получить rootTag, передаваемый из Swift в мой headerLeft() метод?

Я использую эти версии react-native:

react-native-cli: 2.0.1
react-native: 0.61.2

1 Ответ

2 голосов
/ 31 октября 2019

Если вы хотите отклонить встроенный контроллер быстрого просмотра, представленный в RN View

self.dismiss(animated: true, completion: nil)

Я представляю контроллер быстрого просмотра, как показано ниже

 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)
 }

У меня есть расширение наUIApplication, чтобы узнать, какой самый верхний контроллер представления, который используется выше

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
  }
}
...