一、简介

在讲本篇博文之前,需要你熟知怎么自定义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. Vue自定义指令配置修饰符和传参

    一和二,请参考https://www.cnblogs.com/zui-ai-java/p/11109213.html 三.index.html <!DOCTYPE html> <ht ...

  2. 4-2 setting中一定要将ROBOTSTXT_OBEY = False的注释去掉

    # Obey robots.txt rules##默认遵循robots协议的,默认去读取每个网站上的robots协议ROBOTSTXT_OBEY = False

  3. Mac下SVN基本操作和常见错误

    一.基本操作 1  从服务器上下载代码 svn checkout http://xxx.xxx.xxx/xxx 2  获取最新的代码 svn update 3  提交代码 svn commit -m ...

  4. python面向对象之三大特性

    继承 先看个简单的例子了解一下继承. class Animal: # 父类 def __init__(self, name, age, department): self.name = name se ...

  5. MySQL视图 definer & invoker 权限

    1.创建视图 CREATE VIEW `NewView`AS SELECT `user`.USER_ID, `user`.USER_NAME, department.DEPT_ID, departme ...

  6. H3C 三种生成树协议特性的比较

  7. 一排盒子,jq鼠标移入的盒子动画移出停止动画,css动画

    css .category > div.active { animation: servicetobig 0.5s ease 1 forwards; } @keyframes serviceto ...

  8. dotnet core 发布只带必要的依赖文件

    在使用 dotnet core 发布独立项目的时候,会带上大量依赖的库,但是通过微软提供的工具可以去掉一些在代码没有用到的库. 本文介绍的工具是 Microsoft.Packaging.Tools.T ...

  9. CITRIX ADC配置SSL卸载

    如上图,将ssl的加密解密放在前端的负载均衡设备上,客户端到VPX的访问都是加密的,VPX到后端的服务器都是http的 Step1:上传证书到VPX,如下图: Step2:创建SSL的虚拟服务器并且绑 ...

  10. 【一起学源码-微服务】Nexflix Eureka 源码六:在眼花缭乱的代码中,EurekaClient是如何注册的?

    前言 上一讲已经讲解了EurekaClient的启动流程,到了这里已经有6篇Eureka源码分析的文章了,看了下之前的文章,感觉代码成分太多,会影响阅读,后面会只截取主要的代码,加上注释讲解. 这一讲 ...