iOS原生混合RN开发*佳实践

做过原生iOS开发或者Android开发的同学们肯定也都了解Hybrid,有一些Hybrid的开发经验,目前我们企业开发中运用*广泛的Hybrid App技术就是原生与H5 hybrid,在早期的时候,可能部分同学也接触过PhoneGap等hybrid技术,今天我们就简单来聊下一种比较新的Hybrid技术方案,原生App与ReactNativie Hybrid。

示例Demo地址

  • 初级Demo示例
  • 高级Demo示例

具体步骤

  • 创建一个iOS原生项目
  • 将iOS原生项目支持pod
  • 调整目前项目工程的文件夹结构
  • 添加RN依赖相关文件
  • 安装React Native
  • 修改Podfile文件,原生安装React Native依赖库
  • 在iOS原生页面填加RN页面入口
  • 修改RN入口文件 index.ios.js
  • 执行npm start 运行项目

创建一个iOS原生项目

使用Xcode创建一个空的项目,这个应该不用多说了

项目支持pod

这一操作步骤同样也很简单,我们只需要执行下面的几条命令即可,如果对cocoapods 安装使用不熟悉的同学请参照作者简书

  • 创建podfile文件,我们在有xcodeproj文件的同级目录下执行下面命令,这时我们的项目文件中就多了一个Podfile文件
  1. $ pod init
  2. 复制代码
  • 执行pod install 命令来安装pod,同样,这个命令也是在有xcodeproj同级目录下,安装完成后,我们的项目多了一个
  1. $ pod install
  2. 复制代码

注意: 这里对原生iOS不熟悉的同学们需要注意了,当我们使用pod来作为库管理工具,后面我们打开项目运行,我们就需要打开上图所示的xcworkspace文件了

调整目前项目工程的文件夹结构

这里对文件夹做结构调整是为了后期更好的将Android原始项目也使用RN Hybrid,使iOS和Android共享一份React Native框架,共享同一份JS文件,调整的后的文件夹结构如下

添加RN依赖相关文件

到这里,我们原生的iOS项目目录结构已近调整完毕,后面我们需要处理的都是RN相关的内容了,这里需要创建的文件有点多,大家可以直接将示例Demo中的这几个文件直接拖到自己的项目中,然后在做修改即可

  • 首先我们需要创建package.json文件
  • 创建index.ios.js文件
  • 创建index.android.js文件
  • 创建bundle文件夹,注意这个文件夹是后面我们接入CodePush热更新时使用的

安装React Native

安装React Native这个也很简单,我们也是简单的执行下面的命令即可,注意:执行npm 系列的命令,我们都需要在项目根目录(有package.json文件的目录)下执行

  1. $ npm install
  2. 复制代码

package.json文件内容如下

  1. {
  2. “name”: “iOSHybridRNDemo”,
  3. “version”: “0.0.1”,
  4. “private”: true,
  5. “scripts”: {
  6. “start”: “node node_modules/react-native/local-cli/cli.js start”
  7. },
  8. “dependencies”: {
  9. “prop-types”: “^15.6.1”,
  10. “react”: “16.0.0”,
  11. “react-native”: “0.50.3”,
  12. “react-native-code-push”: “^5.2.2”,
  13. “react-native-root-toast”: “^1.3.0”,
  14. “react-native-router-flux”: “^4.0.0-beta.24”,
  15. “react-native-simple-store”: “^1.3.0”,
  16. “react-native-storage”: “^0.2.2”,
  17. “react-native-vector-icons”: “^4.3.0”,
  18. “react-redux”: “^5.0.6”,
  19. “redux”: “^3.7.2”,
  20. “redux-actions”: “^2.2.1”,
  21. “redux-promise-middleware”: “^4.4.1”,
  22. “redux-thunk”: “^2.2.0”
  23. },
  24. “devDependencies”: {
  25. “babel-jest”: “22.4.1”,
  26. “babel-preset-react-native”: “4.0.0”,
  27. “jest”: “22.4.2”,
  28. “react-test-renderer”: “16.0.0”
  29. },
  30. “jest”: {
  31. “preset”: “react-native”
  32. }
  33. }
  34. 复制代码

注意:因为我们项目中使用到了react-native-vector-icons 这个iconFont组件需要依赖原生,所以我们执行完 npm install 之后,我们还需要 再执行一个 react-native link react-native-vector-icons 命令来安装原生依赖

  1. $ react-native link react-native-vector-icons
  2. 复制代码

当我们执行完npm install 命令之后,我们再打开项目目录,发现多了一个 node_modules 文件夹,这个文件夹就是我们安装的React Native所有的依赖库

修改Podfile文件,原生安装React Native依赖库

后面我们都是使用Pod来管理原生的依赖库,安装React Native依赖库,我们只需要将下面的Podfile文件中的内容添加进去,执行 pod install 安装即可

Podfile文件

  1. # Uncomment the next line to define a global platform for your project
  2. platform :ios, ‘9.0’
  3. # Uncomment the next line if you’re using Swift or would like to use dynamic frameworks
  4. # use_frameworks!
  5. target ‘iOSHybridRNDemo’ do
  6. # Pods for iOSHybridRNDemo
  7. #***********************************************************************#
  8. # ‘node_modules’目录一般位于根目录中
  9. # 但是如果你的结构不同,那你就要根据实际路径修改下面的`:path`
  10. pod ‘React’, :path => ‘../node_modules/react-native’, :subspecs => [
  11. ‘Core’,
  12. ‘RCTText’,
  13. ‘RCTImage’,
  14. ‘RCTActionSheet’,
  15. ‘RCTGeolocation’,
  16. ‘RCTNetwork’,
  17. ‘RCTSettings’,
  18. ‘RCTVibration’,
  19. ‘BatchedBridge’,
  20. ‘RCTWebSocket’,
  21. ‘ART’,
  22. ‘RCTAnimation’,
  23. ‘RCTBlob’,
  24. ‘RCTCameraRoll’,
  25. ‘RCTPushNotification’,
  26. ‘RCTLinkingIOS’,
  27. ‘DevSupport’
  28. # 在这里继续添加你所需要的模块
  29. ]
  30. # 如果你的RN版本 >= 0.42.0,请加入下面这行
  31. pod “yoga”, :path => “../node_modules/react-native/ReactCommon/yoga”
  32. #***********************************************************************#
  33. pod ‘RNVectorIcons’, :path => ‘../node_modules/react-native-vector-icons’
  34. end
  35. 复制代码

注意: #*************************# 中间的内容是我们需要添加的RN依赖库,后面我们所有pod 相关的命令,我们都需要iOS根目录(有Podfile文件的目录)下执行

  • 执行安装命令
  1. $ pod install
  2. 复制代码

在iOS原生页面填加RN页面入口

现在我就来实现从原生页面跳RN页面

  • 使用RN提供一个View视图代码如下
  1. NSURL * jsCodeLocation;
  2. #ifdef DEBUG
  3. NSString * strUrl = @“http://localhost:8081/index.ios.bundle?platform=ios&dev=true”;
  4. jsCodeLocation = [NSURL URLWithString:strUrl];
  5. #else
  6. jsCodeLocation = [CodePush bundleURL];
  7. #endif
  8. NSDictionary *params = @{@“componentName”:@“MeApp1”, @“args”:@{@“params”:@“这是原生传递的参数”}};
  9. RCTRootView * rootView = [[RCTRootView alloc] initWithBundleURL:jsCodeLocation
  10. moduleName:@“iOSRN”
  11. initialProperties:params
  12. launchOptions:nil];
  13. self.view = rootView;
  14. 复制代码

修改RN入口文件 index.ios.js

修改RN页面的入口文件,这里当是iOS入口我们修改index.ios.js文件,当Android入口,我们修改index.android.js文件

  • index.ios.js文件
  1. import React, {Component} from ‘react’
  2. import {
  3. Platform,
  4. StyleSheet,
  5. Text,
  6. View,
  7. AppRegistry
  8. } from ‘react-native’;
  9. const instructions = Platform.select({
  10. ios: ‘Press Cmd+R to reload,\n’ +
  11. ‘Cmd+D or shake for dev menu’,
  12. android: ‘Double tap R on your keyboard to reload,\n’ +
  13. ‘Shake or press menu button for dev menu’,
  14. });
  15. type Props = {};
  16. export default class App extends Component<Props> {
  17. render() {
  18. return (
  19. <View style={styles.container}>
  20. <Text style={styles.welcome}>
  21. Welcome to React Native!
  22. </Text>
  23. <Text style={styles.instructions}>
  24. To get started, edit App.js
  25. </Text>
  26. <Text style={styles.instructions}>
  27. {instructions}
  28. </Text>
  29. </View>
  30. );
  31. }
  32. }
  33. const styles = StyleSheet.create({
  34. container: {
  35. flex: 1,
  36. justifyContent: ‘center’,
  37. alignItems: ‘center’,
  38. backgroundColor: ‘#F5FCFF’,
  39. },
  40. welcome: {
  41. fontSize: 20,
  42. textAlign: ‘center’,
  43. margin: 10,
  44. },
  45. instructions: {
  46. textAlign: ‘center’,
  47. color: ‘#333333’,
  48. marginBottom: 5,
  49. },
  50. });
  51. AppRegistry.registerComponent(‘iOSHybridRNDemo’, () => App)
  52. 复制代码

执行npm start 运行项目

到这里,我们一个简单的原生嵌入RN开发工程就搭建完成了,我们执行下面命令来运行项目,查看效果

  • 开启node 服务
  1. $ npm start
  2. 复制代码
  • 运行效果