iOS开发交流专辑手机移动程序开发iOS学习专题

RN环境搭建及与原生交互

2017-03-30  本文已影响1906人  伪文艺的程序员
🇨🇳中文介绍

RN全称React Native,是Facebook公司推出的一款能够跨平台开发的框架,其能够使用js来达到安卓端iOS端共用一套代码开发的目的。React Native的核心设计理念是:即拥有React的开发效率,又能拥有Native的体验。

版本支持

iOS目前支持7.0以上的版本,安卓目前支持4.1以上的版本

开发环境配置

环境要求

安装Homebrew

在终端中输入下面的命令,执行的速度可能比较慢,请耐心等待其执行完成

 ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"

在终端中输入下面的命令验证是否安装成功

 brew -v
安装npm和Node.js

下载地址,下载完成后请手动运行安装,建议使用4.4.4版本

安装watchMan

该插件用于监控bug文件和文件变化,并且可以触发指定的操作,在终端中输入下面的命令就可以了

    brew install watchman

安装Flow

flow是一个JavaScript的静态类型检查器,建议安装它,以方便找出代码中可能存在的类型错误,在终端输入下面的代码,如果提示command not found ,请加上sudo获得最高权限。

    brew install flow

React Native安装

在终端输入

     npm install -g react-native-cli

到这里React Native的环境就已经全部配置好了

创建React Native 项目

在终端中输入下面命令

     react-native init 项目名称

如果速度较慢,可以将npm仓库源替换为国内镜像:

    npm config set registry https://registry.npm.taobao.org
    npm config set disturl https://npm.taobao.org/dist

默认生成了三个文件夹,android和iOS为两个平台的原生项目,index.android.js和index.ios.js为android和iOS平台下的两个空壳应用文件,我们的代码一般就写在这两个文件内,客户端那边不用重新run就可以看到效果,node_modules文件夹主要是存放框架资源。

对index.ios.js文件的编写软件以及提示插件的安装

我们采用的是WebStorm来对js文件来进行编写,由于直接编写并没有代码提示,所以这里要安装一个插件,下载地址,下载完成后file -> import settings -> ReactNative.jar ,完成之后就可以像Xcode那样能够自动提示了.

在现有项目中集成RN

官方推荐的方式是利用CocoaPods
React Native组件植入到iOS应用中有如下几个主要步骤:
1.首先当然要了解你要植入的React Native组件
2.创建一个Podfile,在其中以subspec的形式填写所有你要植入的React Native的组件。
3.创建js文件,编写React Native组件的js代码
4.添加一个事件处理函数,用于创建一个RCTRootView。这个RCTRootView正是用来承载你的React Native 组件的,而且它必须对应你在index.ios.js中使用AppRegistry注册的模块名字。
5.启动React NativePackager服务,运行应用
6.根据需要添加更多的React Native 组件

准备工作

首先确定你的Mac里有没有安装下面的两个环境:

1.react-native
2.CocoaPods

直接在终端敲下面的两个命令,就能看看你有没有装咯

1.react-native -v
2.pod --version

从无到有

如果你是一个小白,那么我们就从头开始吧

1.首先打开我们的Xcode创建一个项目,用终端cd到你刚创建好的项目文件夹中
2.用终端执行pod init 然后再执行 pod install
3.在你的项目文件夹里创建一个文件夹来管理RN,习惯用命令了,直接终端
mkdir  RNUtil
cd RNUtil
4.创建一个package.json的文件
touch package.json
5.在这个文件夹下执行npm install
6.等安装成功后,创建index.ios.js文件,我们就可以开始我们的混编之旅了
touch index.ios.js

Podfile

# Uncomment the next line to define a global platform for your project
platform :ios, ‘8.0’
inhibit_all_warnings!

target 'RNBridgeSwift' do
  # Comment the next line if you're not using Swift and don't want to use dynamic frameworks
  use_frameworks!

  # Pods for RNBridgeSwift

  # react_path 是你react-native文件夹路径。  
  react_path = './RNUtil/node_modules/react-native'
  yoga_path = File.join(react_path, 'ReactCommon/yoga')

  pod 'React', :path => react_path, :subspecs => [
    'Core',
    'RCTText',
    'RCTImage',
    'RCTWebSocket', # needed for debugging
    'RCTNetwork'
  ]
  pod 'Yoga', :path => yoga_path

end

Package.json

{
  "name": "RNBridgeSwift",
  "version": "0.0.1",
  "private": true,
  "scripts": {
    "start": "node node_modules/react-native/local-cli/cli.js start"
  },
  "dependencies": {  
    "react": "15.4.2",  
    "react-native": "0.42.3"
  }
}

Demo

环境搭建好了后,我们就开始搞个小demo玩玩
首先在准备当做原生的页面的Controller里导入React

import React

写点啥好呢,就随便写个按钮加俩Label可以实现页面跳转和传值吧
重点来了哦,在按钮的点击方法里写上下面的代码

  let localJSPath = URL.init(string:"http://localhost:8081/index.ios.bundle?platform=ios")
        
        let params:[String:Array<Dictionary<String, String>>] = [
        
            "scores" : [
                ["name":"Alex","value":"42"],
                ["name":"Joel","value":"10"],
            ]
        ]
        
        let rootView : RCTRootView = RCTRootView(bundleURL: localJSPath, moduleName: "RNTestViewModule", initialProperties: params, launchOptions: nil)

对了,还要创建一个承载js页面的Controller
在这个Controller的viewWillAppear方法里注册两个通知:

 NotificationCenter.default.addObserver(self, selector: #selector(RNManagerViewController.backPreviousVC(_:)), name: NSNotification.Name.init(rawValue: "NotificatioinBack"), object: nil)
        
        NotificationCenter.default.addObserver(self, selector: #selector(RNManagerViewController.backPreviousVC(_:)), name: NSNotification.Name.init(rawValue: "NotificatioinNext"), object: nil)

创建一个类目来诠释通知:

extension RNManagerViewController {
    func backPreviousVC(_ notification: Notification) {
        
        print("current Thread %@",Thread.current)
        
        DispatchQueue.main.async {
            
            if (self.backBlock != nil) {
                self.backBlock!(notification.object ?? "");
            }
            
            if let navigationVC: UINavigationController = self.navigationController, navigationVC.viewControllers.count > 1 {
                
                navigationVC.popViewController(animated: true)
            } else {
                self.dismiss(animated: true, completion: nil)
            }
            
        }
    }
    
    func nextHandle(_ notification: Notification) {
        print("current Thread %@",Thread.current)
        
        DispatchQueue.main.async {
            if (self.backBlock != nil) {
                self.backBlock!(notification.object ?? "");
            }
        }
    }
}

重点来了,引入OC的桥接文件,使RN可以实现OC的方法。

RCT_EXPORT_MODULE(swift);

RCT_EXPORT_METHOD(transportMessage:(id)message){

    NSLog(@"transportMessage:\n %@",message);
    
    if ([message isKindOfClass:[NSDictionary class]]) {
        NSString *method = [message objectForKey:@"method"];
        
        BOOL isNext = method ? ([method isEqualToString:@"push"] || [method isEqualToString:@"present"]) : NO ;
        
        if (isNext) {
            [[NSNotificationCenter defaultCenter] postNotificationName:@"NotificatioinNext" object:message userInfo:nil];
        } else {
            [[NSNotificationCenter defaultCenter] postNotificationName:@"NotificatioinBack" object:message userInfo:nil];
        }
        
    }
}

//RN传参数调用原生OC,并且返回数据给RN  通过CallBack
RCT_EXPORT_METHOD(RNInvokeOCCallBack:(NSDictionary *)dictionary callback:(RCTResponseSenderBlock)callback){
    NSLog(@"接收到RN传过来的数据为:%@",dictionary);
    NSArray *events = @[
                        @{
                            @"name" : @"王垒",
                            @"value": @"111"
                            },
                        @{
                            @"name" : @"King",
                            @"value": @"99"
                            }
                        ];
    
    callback(@[[NSNull null], events]);
}

效果图如下:


RNBridgeSwift.gif

总结

如果你有需要请点下面的按钮前往Clone。

Clone

git clone  https://github.com/KingComeFromChina/RNBridgeSwift.git
上一篇下一篇

猜你喜欢

热点阅读