上一篇介绍了React Native使用react-navigation进行导航跳转页面,现在我们介绍下原生iOS中怎么导航进一个新的React Native页面。
在HYReactNativeManager.h中声明实现声明RCTBridgeDelegate协议,并声明一个全局bridge的属性
@interface HYReactNativeManager : NSObject<RCTBridgeDelegate> + (instancetype)shareInstance; // 全局唯一的bridge @property (nonatomic, readonly, strong) RCTBridge *bridge; @end在HYReactNativeManager.m中实现单例方法、初始化方法、RCTBridgeDelegate协议方法:
#import "HYReactNativeManager.h" @implementation HYReactNativeManager static HYReactNativeManager *_instance = nil; + (instancetype)shareInstance{ if (_instance == nil) { _instance = [[self alloc] init]; } return _instance; } + (instancetype)allocWithZone:(struct _NSZone *)zone{ if (_instance == nil) { static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ _instance = [super allocWithZone:zone]; }); } return _instance; } -(instancetype)init{ if (self = [super init]) { _bridge = [[RCTBridge alloc] initWithDelegate:self launchOptions:nil]; } return self; } #pragma mark - RCTBridgeDelegate - (NSURL *)sourceURLForBridge:(RCTBridge *)bridge { # if DEBUG return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index" fallbackResource:nil]; # else return [[NSBundle mainBundle] URLForResource:@"index" withExtension:@"jsbundle"]; #endif } @end 创建HYReactNativeBaseViewController类,作为新React Native页面的容器类,实现便捷创建方法:HYReactNativeBaseViewController.h完整代码如下:
#import <UIKit/UIKit.h> @interface HYReactNativeBaseViewController : UIViewController /** 传递到React Native的参数 */ @property (nonatomic, strong) NSDictionary * initialProperty; /** React Native界面名称 */ @property (nonatomic, copy) NSString * pageName; + (instancetype)RNPageWithName:(NSString*)pageName initialProperty:(NSDictionary*)initialProperty; - (instancetype)initWithPageName:(NSString*)pageName initialProperty:(NSDictionary*)initialProperty; @endHYReactNativeBaseViewController.m完整代码如下:
#import "HYReactNativeBaseViewController.h" #import <React/RCTRootView.h> #import "HYReactNativeManager.h" @implementation HYReactNativeBaseViewController + (instancetype)RNPageWithName:(NSString*)pageName initialProperty:(NSDictionary*)initialProperty{ HYReactNativeBaseViewController *vc = [[HYReactNativeBaseViewController alloc] initWithPageName:pageName initialProperty:initialProperty]; return vc; } - (instancetype)initWithPageName:(NSString*)pageName initialProperty:(NSDictionary*)initialProperty{ if(self = [super init]){ self.pageName = pageName; self.initialProperty = initialProperty; } return self; } - (void)viewWillAppear:(BOOL)animated{ [super viewWillAppear:animated]; [self.navigationController setNavigationBarHidden:YES]; } - (void)viewWillDisappear:(BOOL)animated{ [super viewWillDisappear:animated]; [self.navigationController setNavigationBarHidden:NO]; } -(void)viewDidLoad{ [super viewDidLoad]; RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:[HYReactNativeManager shareInstance].bridge moduleName:self.pageName initialProperties:self.initialProperty]; self.view = rootView; } @end 将首页按钮点击事件改为: - (void)clickButton:(UIButton*)button{ HYReactNativeBaseViewController *vc = [[HYReactNativeBaseViewController alloc] initWithPageName:@"Navigator" initialProperty:@{}]; [self presentViewController:vc animated:YES completion:nil]; }.m代码:
#import "HYModule.h" @implementation HYModule RCT_EXPORT_MODULE() - (dispatch_queue_t)methodQueue { return dispatch_get_main_queue(); } RCT_EXPORT_METHOD(navigateBack){ [[NSNotificationCenter defaultCenter] postNotificationName:@"HYModuleNavigateBack" object:nil]; } @end 在HYReactNativeBaseViewController.m中添加HYModuleNavigateBack事件监听 @implementation HYReactNativeBaseViewController //...省略代码 - (void)dealloc{ [[NSNotificationCenter defaultCenter] removeObserver:self]; } - (void)navagateBack{ [self.navigationController popViewControllerAnimated:YES]; } - (void)viewDidLoad{ [super viewDidLoad]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(navagateBack) name:@"HYModuleNavigateBack" object:nil]; RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:[HYReactNativeManager shareInstance].bridge moduleName:self.pageName initialProperties:self.initialProperty]; self.view = rootView; } @end在RN页面中,调用导入HYModules并调用HYModules.navigateBack()方法即可通过导航返回页面:
import React, { Component } from 'react'; import {StyleSheet, Image, Text, Button,View, FlatList,TouchableOpacity,NativeModules} from 'react-native'; import { createStackNavigator, createAppContainer } from 'react-navigation' var REQUEST_URL = "https://movie.douban.com/j/search_subjects?type=movie&tag=热门&sort=recommend&page_limit=20&page_start=0" var HYModules = NativeModules.HYModule class LogoTitle extends React.Component { render() { return ( <Image source={require('../image/movie.png')} style={{ width: 30, height: 30 }} /> ); } } export default class HotMovie extends Component<Props> { static navigationOptions = { headerTitle: <LogoTitle />, headerLeft: ( <Button onPress={() => HYModules.navigateBack()} title="首页" color="#fff" /> ), }; _onItemClick(item) { this.props.navigation.navigate('Details',{itemId:item.id,cover:item.cover,title:item.title}) } constructor(props){ super(props); this.state = { movies:null, } this.renderMovie = this.renderMovie.bind(this) this.fetchData = this.fetchData.bind(this) } componentDidMount(){ this.fetchData() } fetchData(){ fetch(REQUEST_URL) .then((response) => response.json()) .then((responseJson) => { this.setState({ movies:responseJson.subjects }); }) } render() { if (!this.state.movies) { return this.renderLoadingView(); } return ( <FlatList data={this.state.movies} renderItem={this.renderMovie} style={styles.list} keyExtractor={item => item.id} /> ); } renderLoadingView(){ return ( <View style={styles.container}> <Text> 正在加载... </Text> </View> ) } renderMovie({item}){ return( <TouchableOpacity style={styles.item} onPress={() => this._onItemClick(item)}> <Image source={{url:item.cover}} style={styles.thumbnail}/> <View style={styles.itemRight}> <Text>{item.title}</Text> <Text>{item.rate}</Text> </View> </TouchableOpacity> ) } } const styles = StyleSheet.create({ container: { flex:1, flexDirection:'row', alignItems:'center', justifyContent: 'center', alignItems: 'center', }, item:{ marginTop:1, flexDirection:'row', alignItems:'center', justifyContent: 'flex-start', height:100, backgroundColor:'lightgray', paddingLeft:10 }, thumbnail:{ width:53, height:81, backgroundColor:'lightgray' }, itemRight:{ height:100, justifyContent: 'center', alignItems:'center', paddingLeft:10 }, list: { backgroundColor: "#F5FCFF" } });完整源代码:https://github.com/dolacmeng/RNProject/tree/master