iOS 应用嵌入 ReactNative 页面
在开发前期首先安装好react native
开发环境、Cocoapods
(可不是用Cocoapods)
React Native 端
首先创建一个js
文件夹 里面包括资源文件,编写一个package.json
文件
package.json
文件内容,声明使用的react版本,并且使用npm install
进行安装node_modules
{
"name": "ProjectName",
"version": "1.0.0",
"private": true,
"description": "ProjectName",
"scripts": {
"start": "node node_modules/react-native/local-cli/cli.js start"
},
"dependencies": {
"react": "~15.3.1",
"react-native": "~0.34.0"
}
}
创建一个index.ios.js
编写react native
页面,这里不再赘述。
Native 端
在Xcode
工程中,创建一个Podfile
文件,声明引入的react
包,文件内容
use_frameworks!
target 'ProjectName'
pod 'React', :path => '../js/node_modules/react-native', :subspecs => [
'Core',
'RCTImage',
'RCTNetwork',
'RCTText',
'RCTWebSocket',
]
使用pod install
进行安装
Xcode
工程中页面不在细说,当那个页面需要使用React Native
页面时,创建一个View
或者ViewController
,在页面中如下所示
import UIKit
//导入React
import React
class AddRatingViewController: UIViewController {
var addRatingView: RCTRootView! //定义一个React 根视图
override func viewDidLoad() {
super.viewDidLoad()
// TODO: 添加一个React View
addRatingView = RCTRootView(
bundleURL: URL(string: "http://localhost:8081/index.ios.bundle?platform=ios"),
moduleName: "AddRatingApp",//react 注册的页面Name
initialProperties: nil,
launchOptions: nil
)
// TODO: 设置视图frame
addRatingView.frame = self.view.bounds
// TODO: 添加到iOS页面上
self.view.addSubview(addRatingView)
}
以上便完成了基本的加载React Native
页面。
加载完页面,接下来就是项目中最主要的传值、方法回调。
Native<->React Native交互
Native
给React
传值。初始化时initialProperties
字段接收一个对象
addRatingView = RCTRootView(
bundleURL: URL(string: "http://localhost:8081/index.ios.bundle?platform=ios"),
moduleName: "AddRatingApp",//react 注册的页面Name
initialProperties: nil,
launchOptions: nil
)
传递后在React Native
端的
AppRegistry.registerComponent()
中注册的初始页面,通过this.props.xxx
获取参数。
方法交互
--
Native 端
加载React native页面要使用RCTBridgeDelegate
协议,并且初始化桥接工具
var bridge: RCTBridge?
func createBridgeIfNeeded() -> RCTBridge {
if bridge == nil {
bridge = RCTBridge.init(delegate: self, launchOptions: nil)
}
return bridge!
}
func viewForModule(_ moduleName: String, initialProperties: [String : Any]?) -> RCTRootView {
let viewBridge = createBridgeIfNeeded()
let rootView: RCTRootView = RCTRootView(
bridge: viewBridge,
moduleName: moduleName,
initialProperties: initialProperties)
return rootView
}
func sourceURL(for bridge: RCTBridge!) -> URL! {
return URL(string:"http://localhost:8081/index.ios.bundle?platform=ios")
}
将bridge
作为参数传递给根视图
let rootView: RCTRootView = RCTRootView(
bridge: viewBridge,
moduleName: moduleName,
initialProperties: initialProperties
)
--
xxx.h
暴露方法给React Native
首先创建一个.h
文件继承RCTEventEmitter
这里使用的swift
语言
import Foundation
import React
@objc(AddRatingManager)
class AddRatingManager: RCTEventEmitter {
//声明监听的方法
override func supportedEvents() -> [String]! {
return ["AddRatingManagerEvent"]
}
//方法一
@objc func dismissPresentedViewController(_ reactTag: NSNumber) {
DispatchQueue.main.async {
if let view = self.bridge.uiManager.view(forReactTag: reactTag) {
let presentedViewController: UIViewController! = view.reactViewController()
presentedViewController.dismiss(animated: true, completion: nil)
}
}
}
//方法二
@objc func save(_ reactTag: NSNumber, rating: Int, forIdentifier identifier: Int) -> Void {
dismissPresentedViewController(reactTag)
// Send an event back to React Native
self.sendEvent(
withName: "AddRatingManagerEvent",
body: ["name": "saveRating", "message": rating, "extra": identifier])
}
}
.m
中声明出RCT_EXTERN_METHOD
#import <Foundation/Foundation.h>
#import "RCTBridgeModule.h"
@interface RCT_EXTERN_MODULE(AddRatingManager, NSObject)
RCT_EXTERN_METHOD(dismissPresentedViewController:(nonnull NSNumber *)reactTag)
RCT_EXTERN_METHOD(save:(nonnull NSNumber *)reactTag rating:(NSInteger *)rating forIdentifier:(NSInteger *)forIdentifier)
@end
--
React Native
端使用
引入NativeModules
,NativeEventEmitter
包
import ReactNative, {
......,
NativeModules,
NativeEventEmitter,
} from 'react-native';
//AddRatingManager 为原生端暴露出的 @objc(AddRatingManager)
const { AddRatingManager } = NativeModules;
在页面的componentDidMount
监听方法componentWillUnmount
移除监听
componentDidMount() {
const AddRatingManagerEvent = new NativeEventEmitter(AddRatingManager);
this._subscription = AddRatingManagerEvent.addListener(
'AddRatingManagerEvent',
(info) => {
console.log(JSON.stringify(info));
}
);
}
componentWillUnmount() {
this._subscription.remove();
}
当React Native需要调用原生方法时
AddRatingManager.dismissPresentedViewController(this.props.rootTag);
AddRatingManager.save(
this.props.rootTag,
this.state.currentRating,
this.state.identifier
);
注意
swift
也需要.m
文件
方法的回调 还有
CallBack()
Promise
等方式,这里不再写。在另一篇文章中查看