Swift初体验ios

iOS 应用嵌入 ReactNative 页面

2017-03-02  本文已影响689人  Mehmet

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交互

NativeReact传值。初始化时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等方式,这里不再写。在另一篇文章中查看

上一篇 下一篇

猜你喜欢

热点阅读