封装iOS原生UI 控件给RN调用

封装原生UI控件给RN调用

前言

前些日子在做项目的时候,接到一个需求:在APP上,点击一个Cell,跳转到拍照页面进行拍照。按理来说,这个需求实现起来,并不困难,第一想法是想直接用 UIImagePickerController 来实现这个需求。后面了解到,UIImagePickerController 实现后的效果是,只能拍一张图片,而不能像系统自带的相机那样,一直拍摄下去。所以又想着说那就直接跳到系统相机去吧!真被我的机智所感动,后面经过一番Google和百度之后,发现,我还是得自己写一个拍照页面。这个时候问题就来了,由于我们的APP是以RN为主的所以需要对原生的功能模块进行一个桥接。这个时候呢,又是通过一整Google和百度,发现,都是一些简单的页面封装。因此也正好借这个机会,写一下自己封装原生UI,以便给需要的童鞋看看,也可以当做自己的一个笔记,回顾一下。OK,废话不多说,我们直接开始动手干吧!

首先,我们需要准备好我们的RN项目,以及要封装的视图。在这里,我先假设各位童鞋都已经有了编写RN项目经验的,如果没有,那就请移步到 React Native中文网 看教程了。

现在以我的项目为例:
首先在我们的Xcode文件中,新建一个 View 用来实现我们要封装的控件功能。我这里取名为 TakePhotoView。然后经过一番编码(具体功能自己实现)之后,TakePhotoView 就可以为我所用。
然后这个时候呢,我们需要再创建一个 View 继承于 RCTViewManager。在我的项目中,我取名为: TakePhotoManager 。这个文件的作用是用来桥接 RN 层于原生层的通信。

TakePhotoManager.h 文件中的代码如下:

//
//  TakePhotoManager.h
//  W00_PRO
//
//  Created by CCYQ on 2018/3/22.
//  Copyright © 2018年 Facebook. All rights reserved.
//

//#import "RCTViewManager.h"
#import <React/RCTViewManager.h>

@interface TakePhotoManager : RCTViewManager<RCTBridgeModule>

@end

这个时候,我们需要对 TakePhotoManager.m 文件进行一些编码,来实现我们的桥接功能。 TakePhotoManager.m 页面的代码如下:

//
//  TakePhotoManager.m
//  W00_PRO
//
//  Created by CCYQ on 2018/3/22.
//  Copyright © 2018年 Facebook. All rights reserved.
//

#import "TakePhotoManager.h"
#import "TakePhotoView.h"

@implementation TakePhotoManager

// 标记宏(必要)
RCT_EXPORT_MODULE()

- (UIView *)view {
  TakePhotoView *takePhotoView = [[TakePhotoView alloc] init];
  return takePhotoView;
}

@end

然后在 RN 的项目中,我们新建一个页面,用来承接这个 TakePhotoManager。在 RN 层中,我们新建一个页面,叫做 TakePhotoiOS.js。在这个页面中,我们需要引入在 原生层中暴露出来的 TakePhoto 页面。所以, TakePhotoiOS.js的代码如下:

### TakePhotoiOS.js
import React, { Component } from 'react';
import {
  AppRegistry,
  StyleSheet,
  Text,
  View,
  requireNativeComponent,
  NativeModules,
} from 'react-native';

// 该方法将 原生层TakePhotoManager 中 return 出来的 View 赋值给 RNTakePhoto。这个时候 RNTakePhoto 就是我们在原生中中的页面了。
// requireNativeComponent() 该方法中有两个参数,第一个是原生层暴露的UIView,另一个是在RN层要承接的 Class。在这里我们可以看到,原生层暴露的UIView的文件叫做 TakePhotoManager,而在这里用的话,只用TakePhoto。这只能说明,原生层的封装需要按照一定的规则来做。
const RNTakePhoto = requireNativeComponent('TakePhoto', TakePhotoiOS);

class TakePhotoiOS extends Component {
   
   
  constructor(props) {
    super(props);
  }

  render() {
    return (
      <RNTakePhoto
        style={styles.container}
      />
    );
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: 'transparent',
  },
});

module.exports = TakePhotoiOS;

到了这一步看似我们的封装工作就完成了。运行一遍,发现没有报错,页面也是正常跳转的;但是呢在这个时候,我们发现,相机的视图是一片空白,并没有按照我们想象中的,出现预览图。这个时候我们检查了代码之后,发现,原来在页面将要加载的时候,我们需要让我们的相机开始工作。那么这个时候,我们就需要在 TakePhotoiOS.js 文件中增加如下代码:

// 视图加载完成
componentDidMount() {
   //需要启动相机
}

// 视图将要消失
componentWillUnmount() {
 //需要关闭相机
}

这个时候问题就来了,我们该怎么暴露我们的方法给 RN 层调用呢?很简单,这个时候我们先在我们的 TakePhotoView.h 文件中,暴露两个方法。代码如下:

//
//  TakePhotoView.h
//  W00_PRO
//
//  Created by CCYQ on 2018/3/22.
//  Copyright © 2018年 Facebook. All rights reserved.
//

#import 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值