RN环境搭建及与原生交互

🇨🇳中文介绍

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
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,189评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,577评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,857评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,703评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,705评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,620评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,995评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,656评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,898评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,639评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,720评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,395评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,982评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,953评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,195评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,907评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,472评论 2 342

推荐阅读更多精彩内容