Как создать мост между Swift и React-Native - PullRequest
0 голосов
/ 14 октября 2019

Я сейчас пробую что-то новое для проекта, над которым работаю.

Мне нужно создать одно представление с помощью React Native, которое должно вызываться из нашего собственного (Swift) приложения.

Для этого необходимо использовать NavigatorBar. Я следовал различным учебникам для того, что мне было нужно:

  1. Интеграция React-Native в существующее приложение для iOS : Это позволило мне нажать VC и отобразитьтекст на экране.

  2. Я создал свой собственный NavigationBar, а затем подумал о том, как отключить текущий (вид RN) после нажатия кнопки, вот когда я нашел этот другой учебник: Руководство по React-Native: интеграция в существующее приложение : Предполагалось, что это позволит мне закрыть текущий VC, создав мост между Swift и RN, но когда я создаю элемент Navigation, япостоянно получаю сообщение об ошибке:

    Invariant Violation: Element type is invalid:
    expected a string (for built-in components) 
    or a class/function (for composite
    components) but got: undefined. You likely
    forgot to export your component from the file
    it's defined in, or you might have mixed up
    default and named imports
    
    Check the render method of `RNHelloWorld`.
    
    This error is located at:
      in RNHelloWorld (at renderApplication.js:40)
      in RCTView (at AppContainer.js:101)
      in RCTView (at AppContainer.js:119)
      in AppContainer (at renderApplication.js:39)
    

Я новичок в React Native, и эти учебники немного устарели, но я не нашел других, которые были обновлены.

Как правильно создать мост между кодом RN и Swift, чтобы можно было отклонить экран на кнопке / тексте с помощью TouchableOpacity?

Вот как мой код Swift для вызова этогоЭкран выглядит так:

fileprivate func loadReactScreen() {
    let images = [UIImage(named: "closeIcon")?.pngData()?.base64EncodedString(),
                  UIImage(named: "image1")?.pngData()?.base64EncodedString()]

    let props: [String : [String?]] = [
        "images": images
    ]
    let rootView = MixerReactModule.sharedInstance.viewForModule("RNHelloWorld", initialProperties: props)

    let vc = UIViewController()
    vc.view = rootView
    self.present(vc, animated: true, completion: nil)
}

import Foundation
import React

class MixerReactModule: NSObject {
    static let sharedInstance = MixerReactModule()
    var bridge: RCTBridge?

    func createBridgeIfNeeded() -> RCTBridge {
        if bridge == nil {
            bridge = RCTBridge.init(delegate: self, launchOptions: nil)
        }
        return bridge!
    }

    func viewForModule(_ moduleName: String, initialProperties: [String : Any]?) -> RCTRootView {
        let viewBridge = createBridgeIfNeeded()
        let rootView: RCTRootView = RCTRootView(
            bridge: viewBridge,
            moduleName: moduleName,
            initialProperties: initialProperties)
        return rootView
    }
}


extension MixerReactModule: RCTBridgeDelegate {
    func sourceURL(for bridge: RCTBridge!) -> URL! {
        return URL(string: "http://0.0.0.0:8081/index.bundle?platform=ios") //IP address points to my localhost, hiding real one from question
    }
}

Теперь мой код React-Native выглядит следующим образом:

index.js

import React from 'react';
import PropTypes from 'prop-types';
import {AppRegistry, NavigatorIOS, Text} from 'react-native'

export default class RNHelloWorld extends React.Component {
    render() {
        return (
            <NavigatorIOS
                initialRoute={{
                    component: MyScene,
                    title: 'Hello, World!'
                }}
            />
        );
    }
}

class MyScene extends React.Component {
    static propTypes = {
        title: PropTypes.string.isRequired,
        navigator: PropTypes.object.isRequired,
    };

    _onForward = () => {
        this.props.navigator.push({
            title: 'Scene'
        })
    };

    render() {
        return (
            <View>
                <Text>Current Scene: {this.props.title}</Text>
            </View>
        )
    }
}

// Module name
AppRegistry.registerComponent('RNHelloWorld', () => RNHelloWorld);

Этокак я это делал перед использованием NavigatorIOS с использованием только Navigator:

<Navigator
    initialRoute={{title: 'WOLOLO'}}
    renderScene={(route, navigator) => <Text>{route.title}</Text>}
    navigationBar={
        <Navigator.NavigationBar
            routeMapper={{
                LeftButton: null,
                RightButton: null,
                Title: (route, navigator, index, navState) =>
                { return (<Text>Awesome Nav Bar</Text>); }
            }}
            style={styles.navBar}
        />
    }
    style={{background: 'gray'}}
/>

Если я включаю navigationBar в компонент Navigation, я получаю другую ошибку, но при ее удалении отображается та же ошибкакак указано выше.

TypeError: undefined is not an object
(evaluating '_reactNative.Navigator.NavigationBar')

This error is located at:
  in RNHelloWorld (at renderApplication.js:40)
  in RCTView (at AppContainer.js:101)
  in RCTView (at AppContainer.js:119)
  in AppContainer (at renderApplication.js:39)

Я считаю, что здесь происходит то, что мои NavigatorIOS (или мои Navigator) равны нулю, потому что я не отправляю их из RCTRootView, если бы это было таккак бы я это сделал?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...