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

MSt*_*pko 6 ios react-native

RN doco和其他示例显示了如何从本机iOS视图控制器启动React-Native视图,但没有相反的方法。有人可以解释我该怎么做吗?

小智 7

使用 Swift 5 更新了这个答案。感谢

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

/sf/answers/3220537631/ - 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)
      }
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

YourViewController.swift

Your regular code
Run Code Online (Sandbox Code Playgroud)

YourApp-桥接标头。请注意,还有一些您可能不需要的额外标头。

#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"
Run Code Online (Sandbox Code Playgroud)

连接文件.swift

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

连接.m

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

@end
Run Code Online (Sandbox Code Playgroud)

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',
  }
});
Run Code Online (Sandbox Code Playgroud)

就是这样,它对我有用,希望对你也有用。再次感谢所有参考资料来源。


MSt*_*pko 6

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

简而言之,答案是使用RCTBridge模块允许RN JavaScript调用本机iOS方法。

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

  1. AppDelegate.h// .m-为初始RN视图初始化RN JavaScript索引文件,还设置了一种方法,用于将根视图控制器交换到本机视图控制器(将从RTCBridge模块调用此方法。

  2. MyViewController.swift- UIViewController具有标准实现的法线。

  3. MyProject-Bridging-Header.h-提供Obj-C <->Swift通讯

  4. ChangeViewBridge.h/ .m-这提供了绑定,使您可以从RN JavaScript调用本机iOS方法。

  5. index.ios.js -初始化您的自定义RCTBridge模块,并调用绑定方法以按一下按钮切换到您的本机视图。

AppDelegate.h

#import <UIKit/UIKit.h>

@interface AppDelegate : UIResponder <UIApplicationDelegate> {
  NSDictionary *options;
  UIViewController *viewController;
}

@property (nonatomic, strong) UIWindow *window;

- (void) setInitialViewController;
- (void) goToRegisterView; // called from the RCTBridge module

@end
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

MyViewController.swift

class RegisterViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        print("MyViewController loaded...")
        // standard view controller will load from RN
    }
}
Run Code Online (Sandbox Code Playgroud)

MyProject-Bridging-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"
Run Code Online (Sandbox Code Playgroud)

ChangeViewBridge.h

#import <React/RCTBridgeModule.h>

@interface ChangeViewBridge : NSObject <RCTBridgeModule>

- (void) changeToNativeView;

@end
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

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);
Run Code Online (Sandbox Code Playgroud)


Cha*_*ani 6

这个解决方案几乎没有改进。使用目前的解决方案,无法从 iOS 返回到 React-Native。

如果你想再次从 iOS 返回到 React-Native。请执行以下操作

 // 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
Run Code Online (Sandbox Code Playgroud)

创建一个返回到 React-native 的按钮,并在按钮操作时关闭此视图控制器:

    // Dismiss the VC so controll go back from iOS to react-native
        [self dismissViewControllerAnimated:TRUE completion:nil];
Run Code Online (Sandbox Code Playgroud)