一、简介

在讲本篇博文之前,需要你熟知怎么自定义ReactNative组件,然后才好学习将自定义的ReactNative组件制作成第三方库。本文中的自定义的ReactNative组件LoginManager API 源自上篇文章,所以需要先看一下上篇博文。言归正传,ReactNative的确提供了一个非常便捷的方式来扩展Native模块。如果要把模块做成第三方组件的话,还有一些工作要做:首先以一个静态库工程来编译模块代码,提供JavaScript的封装,最后创建Package.json来支持node的引用。在步骤开始之前,我先把上篇文章中创建Native原生模块的LoginManager API组件的类贴出来,如下所示:

LoginManager.h

//
// LoginManager.h
// RNDemo
//
// Created by 夏远全 on 2020/1/16.
// Copyright © 2020 Facebook. All rights reserved.
// #import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
#import <React/RCTUtils.h>
#import <React/RCTEventDispatcher.h>
#import <React/RCTBridgeModule.h> NS_ASSUME_NONNULL_BEGIN //OC中定义一个枚举并导出
typedef NS_ENUM(NSInteger, MoveDiretion){
MoveDiretionNone,
MoveDiretionLeft,
MoveDiretionRight,
MoveDiretionBottom,
MoveDiretionTop
}; @interface LoginManager : NSObject<RCTBridgeModule> @end NS_ASSUME_NONNULL_END

LoginManager.m

//
// LoginManager.m
// RNDemo
//
// Created by 夏远全 on 2020/1/16.
// Copyright © 2020 Facebook. All rights reserved.
// #import "LoginManager.h" #ifdef DEBUG
#define NSLog(format, ...) printf("[%s] %s [第%d行] %s\n", __TIME__, __FUNCTION__, __LINE__, [[NSString stringWithFormat:format, ## __VA_ARGS__] UTF8String]);
#else
#define NSLog(format, ...)
#endif @implementation LoginManager //初始化, 添加屏幕旋转监听者
-(instancetype)init {
self = [super init];
if (self) {
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(orientationDidChange:) name:UIDeviceOrientationDidChangeNotification object:nil];
}
return self;
} //导出模块类
RCT_EXPORT_MODULE(); //重映射,auth为code方法的新名称
RCT_REMAP_METHOD(auth,code:(NSString *)account{
NSLog(@"%s---获取验证----",__func__);
NSLog(@"account----%@",account);
}); //login为方法名
RCT_EXPORT_METHOD(login:(NSString *)account password:(NSString *)password{
NSLog(@"%s---登录账号----",__func__);
NSLog(@"account----%@",account);
NSLog(@"password----%@",password);
}); //logout为方法名
RCT_EXPORT_METHOD(logout:(NSString *)account{
NSLog(@"%s---退出账号----",__func__);
NSLog(@"account----%@",account);
}); //设置普通的回调函数
//fetchUserInfoWithToken为方法名,successCallback为成功回调,failureCallback为失败回调
RCT_EXPORT_METHOD(fetchUserInfoWithToken:(NSString *)token success:(RCTResponseSenderBlock)successCallback failure:(RCTResponseErrorBlock)failureCallback
{
if(token.length> && successCallback){
successCallback(@[
@"account = xiayuanquan",
@"password = 123456",
[NSString stringWithFormat:@"token = %@",token]
]);
}
else{
if(failureCallback){
failureCallback(
[[NSError alloc] initWithDomain:NSOSStatusErrorDomain
code:
userInfo: @{NSLocalizedDescriptionKey: @"token exception"}]
);
}
}
}); //设置异步处理的回调函数
//sendMessage为方法名,successCallback为成功回调,failureCallback为失败回调
RCT_EXPORT_METHOD(sendMessage:(NSString *)message success:(RCTPromiseResolveBlock)successCallback failure:(RCTPromiseRejectBlock)failureCallback
{
if(message.length> && successCallback){
successCallback(@"发送成功!");
}
else{
if(failureCallback){
failureCallback(@"",@"发送失败",nil);
}
}
}); //重写constantsToExport, 枚举常量导出
- (NSDictionary<NSString *, id> *)constantsToExport {
return @{
@"MoveDiretionNone": @(MoveDiretionNone),
@"MoveDiretionLeft": @(MoveDiretionLeft),
@"MoveDiretionRight": @(MoveDiretionRight),
@"MoveDiretionBottom": @(MoveDiretionBottom),
@"MoveDiretionTop": @(MoveDiretionTop)
};
} //定义一个移动方法,根据传入的枚举值移动
//move为方法名
RCT_EXPORT_METHOD(move:(MoveDiretion)moveDiretion{
switch(moveDiretion){
case MoveDiretionNone:
NSLog(@"仍保持原始位置 --- MoveDiretionNome");
break;
case MoveDiretionLeft:
NSLog(@"向左边移动位置 --- MoveDiretionLeft");
break;
case MoveDiretionRight:
NSLog(@"向右边移动位置 --- MoveDiretionRight");
break;
case MoveDiretionBottom:
NSLog(@"向下边移动位置 --- MoveDiretionBottom");
break;
case MoveDiretionTop:
NSLog(@"向上边移动位置 --- MoveDiretionTop");
break;
}
}); //可以重写队列,给当前模块类指定自定义的串行队列。若不指定,则系统默认会给当前模块类随机分配一个串行队列。
//这个方法一旦重写。当前模块的所有方法均会在该自定义的串行队列中异步执行
-(dispatch_queue_t)methodQueue{
return dispatch_queue_create("com.facebook.ReactNative.LoginManagerQueue", DISPATCH_QUEUE_SERIAL);
} //定义一个方法,获取线程和队列信息
//thread为方法名
RCT_EXPORT_METHOD(thread:(BOOL)newQueue{ const char *queueName = dispatch_queue_get_label([self methodQueue]);
NSLog(@"当前线程1 ------- %@-----%s", [NSThread currentThread], queueName); if(newQueue){ dispatch_async(dispatch_get_main_queue(), ^{
const char *queueName2 = dispatch_queue_get_label(dispatch_get_main_queue());
NSLog(@"当前线程2 ------- %@ -------%s", [NSThread currentThread], queueName2);
}); dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, ), ^{
const char *queueName3 = dispatch_queue_get_label(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, ));
NSLog(@"当前线程3 ------- %@-------%s", [NSThread currentThread], queueName3);
});
}
}); //获取当前屏幕的尺寸
static NSDictionary *Dimensions(){
CGFloat width = MIN(RCTScreenSize().width, RCTScreenSize().height);
CGFloat height = MAX(RCTScreenSize().width, RCTScreenSize().height);
CGFloat scale = RCTScreenScale();
if(UIDeviceOrientationIsLandscape([UIDevice currentDevice].orientation)){
width = MAX(RCTScreenSize().width, RCTScreenSize().height);
height = MIN(RCTScreenSize().width, RCTScreenSize().height);
}
return @{
@"width": @(width),
@"height": @(height),
@"scale": @(scale)
};
}
//定义一个方法,获取屏幕信息
//getDimensions为方法名
RCT_EXPORT_METHOD(getDimensions:(RCTResponseSenderBlock)callback{
if (callback) {
callback(@[[NSNull null], Dimensions()]);
}
}); //监听方法,使用RCTEventDispatcher的eventDispatcher调用sendDeviceEventWithName函数发送事件信息
//可以将事件名称作为常量导出,提供给ReactNative中使用,也即添加到constantsToExport方法中的字典中即可。类似上面的枚举。
@synthesize bridge = _bridge;
-(void)orientationDidChange:(NSNotification *)notification {
[_bridge.eventDispatcher sendDeviceEventWithName:@"orientationDidChange" body:@{
@"orientation": UIDeviceOrientationIsLandscape([UIDevice currentDevice].orientation) ? @"Landscape": @"Portrait",
@"Dimensions": Dimensions()}
];
} //移除监听者
-(void)dealloc{
[[NSNotificationCenter defaultCenter] removeObserver:self];
} @end

RCTConvert+MoveDiretion.h

//
// RCTConvert+MoveDiretion.h
// RNDemo
//
// Created by 夏远全 on 2020/1/17.
// Copyright © 2020 Facebook. All rights reserved.
// #import <React/RCTConvert.h> NS_ASSUME_NONNULL_BEGIN @interface RCTConvert (MoveDiretion) @end NS_ASSUME_NONNULL_END

RCTConvert+MoveDiretion.m

//
// RCTConvert+MoveDiretion.m
// RNDemo
//
// Created by 夏远全 on 2020/1/17.
// Copyright © 2020 Facebook. All rights reserved.
// #import "RCTConvert+MoveDiretion.h"
#import "LoginManager.h" @implementation RCTConvert (MoveDiretion) //给RCTConvert类添加扩展,这样在模块方法调用中使用常量导出的枚举值,通信到Native中时,会从整型自动转换为定义的枚举类型
RCT_ENUM_CONVERTER(MoveDiretion,(@{
@"MoveDiretionNone": @(MoveDiretionNone),
@"MoveDiretionLeft": @(MoveDiretionLeft),
@"MoveDiretionRight": @(MoveDiretionRight),
@"MoveDiretionBottom": @(MoveDiretionBottom),
@"MoveDiretionTop": @(MoveDiretionTop),
}), MoveDiretionNone, integerValue) @end

二、步骤

1、使用xcode创建一个名为LoginManager的静态库。

2、打开静态库,将上面贴出来的已经实现好了的Native模块LoginManager API组件的类全部拷贝进去或进行替换。

3、选择Build Settings,配置Header Search Paths路径。

6、打开终端,初始化一个新的RN项目,随意设置一个名称为:LoginManagerTestProject。(本人安装的ReactNative版本较低)

//初始化
react-native init LoginManagerTestProject --version 0.44.

7、进入目录node_modules。

//进入node_modules
cd LoginManagerTestProject/node_modules

8、创建要制作的第三库文件夹,指定名称为:react-native-login-manager。

//创建第三方名称
mkdir react-native-login-manager

9、进入这个第三方库文件夹。

//进入库文件
cd react-native-login-manager

10、创建ios文件夹。

//创建ios文件
mkdir ios

11、将之前创建的静态库中的根目录下的文件全部copy到这个RN工程LoginManagerTestProject/node_modules/react-native-login-manager/ios目录下。目录结构如下:

12、使用xcode打开这个RN工程LoginManagerTestProject,将静态库LoginManager的.xcodeproj文件 拖到 RN工程LoginManagerTestProject的Libraries文件下。

13、手动添加libLoginManager.a静态包,然后编译,如果编译不出错,则success。

14、使用终端或者webStorm等编程工具进入到RN工程LoginManagerTestProject/node_modules/react-native-login-manager目录下,创建index.js文件,它是整个原生模块的入口,我们这里只是将原生LoginManager模块类进行导出。此时也就完成了第三方库制作的第一步了,仅仅可以自己使用。 (还需要发布到npm上,分享给大家安装使用)

三、测试

好了,咱先自己测试一下,看看行不行。结果是行的,

ReactNative: 将自定义的ReactNative组件制作成第三方库的详细流程(制作-->发布)的更多相关文章

  1. vue 移动端轻量日期组件不依赖第三方库

    Vue版移动端日期选择组件 1.优点:不需要依赖其他第三方库,灵活可配置: 不需要依赖第三方组件的vue日期移动端组件  小轮子 轻量可复用:  https://github.com/BeckReed ...

  2. Qt动态库静态库的创建、使用、多级库依赖、动态库改成静态库等详细说明

    本文描述的是windows系统下,通过qtcreator在pro文件中添加动态库与静态库的方法: 1.添加动态库(直接添加动态库文件.dll,非子项目) 通过qtcreator创建动态库的方法就不在此 ...

  3. ReactNative: 创建自定义List列表组件

    一.介绍 在App中,很多数据消息显示都是一行行动态展示的,例如新闻标题,其实每一条新闻标题都可以独立成一个简单的列表组件,之前我们使用Text组件将数据都写死了,为了提高组件的灵活性,我们可以使用T ...

  4. Egret第三方库的制作和使用(模块化 第三方库)

    一.第三方库的制作 官方教程:第三方库的使用方法 水友帖子:新版本第三方库制作细节5.1.x 首先在任意需要创建第三方库的地方,右键,选择"在此处打开命令窗口" 输入egret c ...

  5. Egret的第三方库制作,以及在大型项目中的应用

    目录: 一 创建第三方库 二 TypeScript库 三 JavaScript库 四 第三方库制作在大型RPG中的实际应用 参考: 第三方库的使用方法 目标: 本文目的是将现有游戏的框架制作成第三方库 ...

  6. ReactNative Android之原生UI组件动态addView不显示问题解决

    ReactNative Android之原生UI组件动态addView不显示问题解决 版权声明:本文为博主原创文章,未经博主允许不得转载. 转载请表明出处:http://www.cnblogs.com ...

  7. React Native实战系列教程之自定义原生UI组件和VideoView视频播放器开发

    React Native实战系列教程之自定义原生UI组件和VideoView视频播放器开发   2016/09/23 |  React Native技术文章 |  Sky丶清|  4 条评论 |  1 ...

  8. react-native技术调研:react-native是什么?

    如有疏漏错误,还望指正.转载不忘加上>>原链接<<哦~ react-native是什么? react-native原理 从字面意思上来看,react-native由单词reac ...

  9. iOS开发之自定义表情键盘(组件封装与自动布局)

    下面的东西是编写自定义的表情键盘,话不多说,开门见山吧!下面主要用到的知识有MVC, iOS开发中的自动布局,自定义组件的封装与使用,Block回调,CoreData的使用.有的小伙伴可能会问写一个自 ...

随机推荐

  1. linux /proc 接口

    无论何时一个硬件中断到达处理器, 一个内部的计数器递增, 提供了一个方法来检查设备 是否如希望地工作. 报告的中断显示在 /proc/interrupts. 下面的快照取自一个双处理 器 Pentiu ...

  2. CF1151FSonya and Informatics

    CF1151FSonya and Informatics 给一个长度为 n$ (n\leq 100)$的 \(0/1\) 串,进行 k\((k \leq 10^9)\)次操作,每次操作选择两个位置 \ ...

  3. ES基本语法

    7.2.0版本 1 创建库 http://{ip}:{port}/{库名称} put 2 查询库 http://{ip}:{port}/_cat/indices?v get health status ...

  4. ELK系统分析nginx日志

    一.nginx nginx 服务器日志的log_format格式: log_format main '$remote_addr - $remote_user [$time_local] "$ ...

  5. 防火墙TCP的单向控制

    网络拓扑: 如上图所示,防火墙分为external/internal/dmz三个安全zone,其中10.133.1.100/32为dmz区的一台squid缓存服务器,10.158.1.10/32,10 ...

  6. Windows 服务安装与卸载 (通过 installutil.exe)

    1. 安装 安装 .NET Framework ; 新建文本文件,重命名为 ServiceInstall.bat,将 ServiceInstall.bat 的内容替换为: C:\\Windows\\M ...

  7. 在linux下find和grep

    在linux下面工作,有些命令能够大大提高效率.本文就向大家介绍find.grep命令,他哥俩可以算是必会的linux命令,我几乎每天都要用到他们.本文结构如下: find命令 find命令的一般形式 ...

  8. 什么?我往Redis写的数据怎么没了?

    大概是因为int没有因为change方法而改变原值,所以就说它传过去的是自身的值,因而叫值传递:User对象经过change方法后,对象的数据变了,就认为是因为实参和形参指向的是同一片内存空间,内存空 ...

  9. Visual Studio 2019使用docker开发(vsdbg的问题)

    前言 vsdbg在国内下载的速度真的很慢,借助迅雷也没办法起飞. 这里还是来探讨下如何用迅雷进行下载以后安装操作. 遇到的状况 在使用Visual Studio 2019进行开发调试(https:// ...

  10. select * from user 这条 SQL 语句,背后藏着哪些不可告人的秘密?

    作为一名 Java开发人员,写 SQL 语句是常有的事,但是你知道 SQL 语句背后的处理逻辑吗?比如下面这条 SQL 语句: select * from user where id=1 执行完这条语 ...