React-Native iOS - 如何通过按下按钮从React-Native视图导航到非React-Native视图(本机iOS视图控制器)?

时间:2017-08-17 17:48:47

标签: ios react-native

RN doco和其他示例显示了如何从本机iOS视图控制器启动React-Native视图,但不是相反。有人可以解释我怎么做到这一点吗?

3 个答案:

答案 0 :(得分:3)

使用Swift 5对此问题进行更新。

https://github.com/facebook/react-native/issues/1148#issuecomment-102008892

https://stackoverflow.com/a/46007680/7325179-MStrapko的回答

https://codersera.com/blog/react-native-bridge-for-ios/?unapproved=2851&moderation-hash=77e42524b246d2fda0f763a496156db5#comment-2851-William Dawson的详尽解释和教程

进入解决方案:

在AppDelegate.swift中

import Foundation
import UIKit

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
  var window: UIWindow?
  var bridge: RCTBridge!
  
  func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
    let jsCodeLocation: URL
    
    jsCodeLocation = RCTBundleURLProvider.sharedSettings().jsBundleURL(forBundleRoot: "index.js", fallbackResource:nil)
    let rootView = RCTRootView(bundleURL: jsCodeLocation, moduleName: "RNModuleName", initialProperties: nil, launchOptions: launchOptions)
    
    self.window = UIWindow(frame: UIScreen.main.bounds)
    let reactNativeViewController = UIViewController()
    reactNativeViewController.view = rootView
    let reactNavigationController = UINavigationController(rootViewController: reactNativeViewController)
    self.window?.rootViewController = reactNavigationController
    self.window?.makeKeyAndVisible()
    
    return true
  }
//  func goToReactNative() {
//    window?.rootViewController?.dismiss(animated: true)
//  }
  func goNativeStoryboard() {
    DispatchQueue.main.async {
      let vc = UIStoryboard(name: "Main", bundle: nil).instantiateInitialViewController()
      if let vc = vc {
        (self.window?.rootViewController as? UINavigationController)?.pushViewController(vc, animated: true)
      }
    }
  }
}

YourViewController.swift

Your regular code

YourApp-Bridging-Header。请注意,还有一些多余的标题,您可能不需要。

#import "React/RCTBridgeModule.h"
#import "React/RCTBridge.h"
#import "React/RCTEventDispatcher.h"
#import "React/RCTRootView.h"
#import "React/RCTUtils.h"
#import "React/RCTConvert.h"
#import "React/RCTBundleURLProvider.h"
#import "RCTViewManager.h"
#import "React/RCTEventEmitter.h"

ConnectingFile.swift

@objc(Connect)
class Connect: NSObject {
  @objc func goToNative() -> Void {
    DispatchQueue.main.async {
      if let appDelegate = UIApplication.shared.delegate as? AppDelegate {
        appDelegate.goNativeStoryboard()
      }
    }
  }
}

Connect.m

#import "React/RCTViewManager.h"
@interface RCT_EXTERN_MODULE(Connect, RCTViewManager)
RCT_EXTERN_METHOD(goToNative)

@end

ReactNativeFile.js

import React, { Component } from 'react';
import { StyleSheet, View, NativeModules, Text, TouchableOpacity } from 'react-native';
const { Connect } = NativeModules;
export default class Feed extends Component {
  constructor(props) {
    super(props)
    this.done = false;
  }
  _changeView() {
    this.done = true;
    Connect.goToNative()
  }
  render() {
    return (
      <View style={styles.container}>
        <TouchableOpacity onPress={() => this._changeView()}>
          <Text color="#336699">
            Press to Change to Native View
            </Text>
        </TouchableOpacity>
      </View>
    );
  }
}
const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: 'pink',
    alignItems: 'center',
    justifyContent: 'center',
  }
});

就是这样,它对我有用,希望它对您也有用。再次感谢所有引用来源。

答案 1 :(得分:2)

我能够弄清楚这一点。在我的情况下,我使用我自己的Swift本机视图控制器的Obj-C基础项目(这是RN默认值)。我的解决方案就在这里,以防其他人出现:

简单地说,答案是使用RTCBridge模块允许RN javascript调用本机iOS方法。

以下是组件的概述,然后是实现:

  1. AppDelegate.h / .m - 初始化初始RN视图的RN javascript索引文件,还设置了将根视图控制器交换到本机视图控制器的方法(此方法将从RTCBridge模块调用。
  2. MyViewController.swift - 具有标准实现的普通UIViewController。
  3. MyProject-Bridging-Header.h - 提供Obj-C&lt; - &gt;快速沟通
  4. ChangeViewBridge.h / .m - 这提供了绑定,允许您从RN javascript调用本机iOS方法
  5. index.ios.js - 初始化自定义RCTBridge模块,并通过按下按钮调用绑定方法切换到本机视图。
  6. AppDelegate.h

    #import <UIKit/UIKit.h>
    
    @interface AppDelegate : UIResponder <UIApplicationDelegate, IXUAFDelegate> {
      NSDictionary *options;
      UIViewController *viewController;
    }
    
    @property (nonatomic, strong) UIWindow *window;
    
    - (void) setInitialViewController;
    - (void) goToRegisterView; // called from the RCTBridge module
    
    @end
    

    AppDelegate.m

    #import "AppDelegate.h"
    #import <React/RCTBundleURLProvider.h>
    #import <React/RCTRootView.h>
    #import "FidoTestProject-Swift.h" // Xcode generated import to reference MyViewController.swift from Obj-C
    
    @implementation AppDelegate
    
    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
    {
      options = launchOptions;
      [self setInitialViewController];
      return YES;
    }
    
    - (void) setInitialViewController {
      NSURL *jsCodeLocation;
    
      jsCodeLocation = [NSURL URLWithString:@"http://192.168.208.152:8081/index.ios.bundle?platform=ios&dev=true"];
    
      RCTRootView *rootView = [[RCTRootView alloc] initWithBundleURL:jsCodeLocation moduleName:@"FidoTestProject" initialProperties:nil launchOptions:options];
    
      self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
      UIViewController *rootViewController = [UIViewController new];
      rootViewController.view = rootView;
      self.window.rootViewController = rootViewController;
    
      viewController = rootViewController;
    
      [self.window makeKeyAndVisible];
    }
    
    // this method will be called from the RCTBridge
    - (void) goToNativeView {
      NSLog(@"RN binding - Native View - MyViewController.swift - Load From "main" storyboard);
      UIViewController *vc = [UIStoryboard storyboardWithName:@"main" bundle:nil].instantiateInitialViewController;
      self.window.rootViewController = vc;
    }
    
    @end
    

    MyViewController.swift

    class RegisterViewController: UIViewController {
    
        override func viewDidLoad() {
            super.viewDidLoad()
            print("MyViewController loaded...")
            // standard view controller will load from RN
        }
    }
    

    MyProject的桥接-Header.h

    @import Foundation;
    @import UIKit;
    @import CoreLocation;
    @import AVFoundation;
    
    #import "React/RCTBridge.h"
    #import "React/RCTBridgeModule.h"
    #import "React/RCTBundleURLProvider.h"
    #import "React/RCTRootView.h"
    #import "AppDelegate.h"
    

    ChangeViewBridge.h

    #import <React/RCTBridgeModule.h>
    
    @interface ChangeViewBridge : NSObject <RCTBridgeModule>
    
    - (void) changeToNativeView;
    
    @end
    

    ChangeViewBridge.m

    #import "RegisterBridge.h"
    #import "FidoTestProject-Swift.h"
    #import "AppDelegate.h"
    
    @implementation ChangeViewBridge
    
    // reference "ChangeViewBridge" module in index.ios.js
    RCT_EXPORT_MODULE(ChangeViewBridge);
    
    RCT_EXPORT_METHOD(changeToNativeView) {
      NSLog(@"RN binding - Native View - Loading MyViewController.swift");
      AppDelegate *appDelegate = (AppDelegate *)[UIApplication sharedApplication].delegate;
      [appDelegate goToNativeView];
    }
    
    @end
    

    index.ios.js

    /**
     * Sample React Native App
     * https://github.com/facebook/react-native
     * @flow
     */
    
    'use strict';
    
    import React, { Component } from 'react';
    import {
      AppRegistry,
      StyleSheet,
      Alert,
      Text,
      View,
      NativeModules,
      TouchableHighlight
    } from 'react-native';
    
    export default class FidoTestProject extends Component {
    
      constructor(props) {
         super(props)
         this.done = false;
       }
    
        _changeView() {
          this.done = true;
          this.render();
          NativeModules.ChangeViewBridge.changeToNativeView();
        }
    
      render() {
        if (!this.done) {
          return (
            <View style={styles.container}>
              <TouchableHighlight onPress={() => this._changeView()}>
                <Text color="#336699">
                  Press to Change to Native View
                </Text>
              </TouchableHighlight>
            </View>
          );
        } else {
          return (<View></View>);
        }
      }
    };
    
    const styles = StyleSheet.create({
      container: {
        flex: 1,
        justifyContent: 'center',
        alignItems: 'center',
        backgroundColor: '#F5FCFF',
      }
    });
    
    AppRegistry.registerComponent('FidoTestProject', () => FidoTestProject);
    

答案 2 :(得分:0)

There is little improvement on this solution.With present solution there is no way to come back to React-Native from iOS. 

If you want to come back again from iOS to React-Native.Do the below

 // AppDelegate.h

    - (void) goToNativeView {
     UIViewController *vc =  [InitialViewController new];// This is your native iOS VC
     UINavigationController* navigationController = [[UINavigationController alloc] initWithRootViewController:vc];

      dispatch_async(dispatch_get_main_queue(), ^{
       // Never do the below, it will be difficult to come back to react-native

       // self.window.rootViewController = navigationController;

        // Do this instead
        [self.window.rootViewController presentViewController:navigationController animated:true completion:NULL];
      });
    }

//InitialViewController.m

    **-Create a button for go back to React-native and on button action dismiss this view controller like below.**

    // Dismiss the VC so controll go back from iOS to react-native
        [self dismissViewControllerAnimated:TRUE completion:nil];