iOS--React Native密码键盘插件(内附Demo)

一:介绍

React Native (简称RN)是Facebook于2015年4月开源的跨平台移动应用开发框架,是Facebook早先开源的JS框架 React 在原生移动应用平台的衍生产物,目前支持iOS和安卓两大平台。RN使用Javascript语言,类似于HTML的JSX,以及CSS来开发移动应用,因此熟悉Web前端开发的技术人员只需很少的学习就可以进入移动应用开发领域。

在React Native移动平台项目开发中,除了React Native 提供的封装好的部分插件和原声组建外,在实际的项目中还需要使用到很多其他的插件,比如网络请求、数据库、相机、相册、通讯录、视频播放器、浏览器、蓝牙连接、图片处理、消息推送、地图、统计、埋点等等APP开发中需要用到的功能,都为IDE开发平台提供封装好的插件,以便项目开发使用。

另外,这些博文都是来源于我日常开发中的技术总结,在时间允许的情况下,我会针对技术点分别分享iOS、Android两个版本,如果有其他技术点需要,可在文章后留言,我会尽全力帮助大家。这篇文章重点介绍原生密码键盘插件的开发与使用

源码Demo获取方法

如果需要React Native密码键盘插件源码demo,欢迎关注 【网罗开发】微信公众号,回复【62】便可领取。
网罗天下方法,方便你我开发,所有文档会持续更新,欢迎关注一起成长!

二:实现思路分析

原生密码键盘插件是需要实现自定以键盘包含数字、大写字母、小写字母、特殊字符四种切换方式,并且需要实现随机键盘和非随机键盘模式。
实现根据密码包含数字、大写字母、小写字母、特殊字符种类判断密码强度和长度。
为了密码的安全考虑,实现对输出密码进行SM3加密。
实现键盘类型,其中包括以下6种类型:

FBYCustomKeyBordType_NumWord,//数字及字母键盘
FBYCustomKeyBordType_WordNum,//字母及数字键盘
FBYCustomKeyBordType_NumWordSymbol,//数字及字母,标点键盘
FBYCustomKeyBordType_WordNumSymbol,//字母及数字,标点键盘
FBYCustomKeyBordType_Num,//仅数字键盘
FBYCustomKeyBordType_Word//仅字母键盘

基本键盘截图如下:


66.png

实现键盘视图显示类型,其中包括以下5种类型:

FBYCustomKeyBordShowType_Common,//普通
FBYCustomKeyBordShowType_Text,//文本框
FBYCustomKeyBordShowType_Pass,//密码
FBYCustomKeyBordShowType_PayPass,//支付密码格
FBYCustomKeyBordShowType_NoTitle//无标题

带有文本框的键盘:


88.png

有支付密码格的键盘:


99.png

打开默认浏览器和打开自定义浏览器,具体的实现思路如下:

  1. 新建CustomKeyboard类,实现RCTBridgeModule协议

  2. 添加RCT_EXPORT_MODULE()宏

  3. 添加React Native跟控制器

  4. 声明被JavaScript 调用的方法

  5. 新建数字键盘FBYNumKeyBord类,实现相应视图及功能

  6. 新建字母键盘FBYWordKeyBord类,实现相应视图及功能

  7. 新建纯数字键盘FBYNumOnlyKeyBord类,实现相应视图及功能

  8. 新建符号键盘FBYSymbolKeyBord类,实现相应视图及功能

  9. 新建符号键盘FBYCustomKeyBord类,实现键盘类型切换功能

  10. 实现根据密码判断密码强度和长度功能

  11. 实现输出密码SM3加密功能

  12. 根据传参分析调用自定义键盘

  13. Javascript调用浏览器方法

三:实现源码分析

1. 新建CustomKeyboard类,实现RCTBridgeModule协议

新建继承NSObject的CustomKeyboard类,并实现RCTBridgeModule协议

// CustomKeyboard.h
#import <Foundation/Foundation.h>
#import <React/RCTBridgeModule.h>
#import <UIKit/UIKit.h>
@interface CustomKeyboard : NSObject<RCTBridgeModule>
@end
2. 添加RCT_EXPORT_MODULE()宏

为了实现RCTBridgeModule协议,CustomKeyboard的类需要包含RCT_EXPORT_MODULE()宏。
并在这个宏里面添加一个参数“KeybordPlugin”用来指定在 JavaScript 中访问这个模块的名字。
如果你不指定,默认就会使用这个 Objective-C 类的名字。
如果类名以 RCT 开头,则 JavaScript 端引入的模块名会自动移除这个前缀。

// CustomKeyboard.m
#import "CustomKeyboard.h"
@implementation CustomKeyboard
RCT_EXPORT_MODULE(KeybordPlugin);
@end
3. 添加React Native跟控制器

如果不添加React Native跟控制器,view将不能正常显示出来,实现方法如下:

// CustomKeyboard.m
#import "CustomKeyboard.h"
#import <React/RCTUtils.h>
@implementation CustomKeyboard
RCT_EXPORT_MODULE(KeybordPlugin);
@end

引入<React/RCTUtils.h>之后,在视图初始化或者显示的时候,按照如下方法调用即可

UIViewController *vc = RCTPresentedViewController();
4. 声明被JavaScript 调用的方法

React Native需要明确的声明要给 JavaScript 导出的方法,否则 React Native 不会导出任何方法。声明通过RCT_EXPORT_METHOD()宏来实现:

// CustomKeyboard.m
#import "CustomKeyboard.h"
#import <React/RCTUtils.h>
@implementation CustomKeyboard
RCT_EXPORT_MODULE(KeybordPlugin);
RCT_EXPORT_METHOD(onKeyboard:(NSDictionary *)arguments
                  :(RCTResponseSenderBlock)sucessCallback
                  :(RCTResponseSenderBlock)failCallback)
{
    NSLog(@"调起原生密码键盘方法");
}
@end
5. 新建数字键盘FBYNumKeyBord类,实现相应视图及功能

在数字键盘FBYNumKeyBord类中,视图包含0-9数字按钮、ABC字母切换按钮、@%#特殊字符切换按钮、回删按钮、完成按钮和取消按钮。
实现相应按钮的点击功能以及实现随机键盘和非随机键盘两种模式。
效果图:

number.png

核心代码如下:

//FBYNumKeyBord.m
- (void)setRandom:(BOOL)random{
    _random = random;
    if (random) {
        NSMutableArray *newArray = [NSMutableArray arrayWithArray:self.numArray];
        for(int i = 0; i< self.numArray.count; i++)
        {
            int m = (arc4random() % (self.numArray.count - i)) + i;
            [newArray exchangeObjectAtIndex:i withObjectAtIndex: m];
        }
        self.numArray = newArray;
        for (UIButton *btn in self.subviews) {
            [btn removeFromSuperview];
        }
        [self addControl];
    }
}
6. 新建字母键盘FBYWordKeyBord类,实现相应视图及功能

在数字键盘FBYWordKeyBord类中,视图包含26个字母按钮、大小写切换按钮、123数字键盘切换按钮、@%#特殊字符切换按钮、回删按钮、完成按钮和取消按钮。
实现相应按钮的点击功能以及实现随机键盘和非随机键盘两种模式。
效果图:

1234.png

核心代码如下:

//FBYWordKeyBord.m
for (int i = 0; i< 26; i++) {
        FBYCustomKeyBordButton *btn = [FBYCustomKeyBordButton buttonWithTitle:self.wordArray[i] tag:i delegate:self];
        [btn addTarget:self action:@selector(btnTouchDown:) forControlEvents:(UIControlEventTouchDown)];
         [btn addTarget:self action:@selector(btnTouchCancel:) forControlEvents:(UIControlEventTouchUpInside)];
        [btn addTarget:self action:@selector(btnTouchCancel:) forControlEvents:(UIControlEventTouchUpOutside)];
         [btn addTarget:self action:@selector(btnTouchCancel:) forControlEvents:(UIControlEventTouchCancel)];
        [btnArray addObject:btn];
        [self addSubview:btn];
    }
7. 新建纯数字键盘FBYNumOnlyKeyBord类,实现相应视图及功能

在数字键盘FBYNumOnlyKeyBord类中,视图包含0-9数字按钮、回删按钮、完成按钮和取消按钮。
实现相应按钮的点击功能以及实现随机键盘和非随机键盘两种模式。
效果图:

0987.png

核心代码如下:

//FBYNumOnlyKeyBord.m
for (int i=0;i<self.btnArray.count;i++) {
        UIButton *btn =self.btnArray[i];
        if(i<9){
            btn.frame = CGRectMake(btn.tag % 3 * (btnW ), btn.tag / 3 * (btnH ), btnW, btnH);
        }else if (i==9){
            btn.frame = CGRectMake( 1 * (btnW ),  3* (btnH ), btnW, btnH);
        }else if (i==10){
            btn.frame = CGRectMake( 0* (btnW ),  3* (btnH ) , btnW, btnH);
            
        }else if (i==11){
            btn.frame = CGRectMake( 2* (btnW ), 3* (btnH ), btnW, btnH);
        }else if (i==12){
            btn.frame = CGRectMake( 0* (btnW ), 3* (btnH ), btnW, btnH);
        }  
    }
8. 新建符号键盘FBYSymbolKeyBord类,实现相应视图及功能

在数字键盘FBYSymbolKeyBord类中,视图包含30种特殊字符按钮、123数字键盘切换按钮、ABC字母切换按钮、回删按钮、完成按钮和取消按钮。
实现相应按钮的点击功能以及实现随机键盘和非随机键盘两种模式。
效果图:

4321.png

核心代码如下:

//FBYSymbolKeyBord.m
- (NSArray *)symbolArray{
    if (!_symbolArray) {
        _symbolArray = @[@"*",@"/",@":",@";",@"(",@")",@"[",@"]",@"$",@"=",@"!",@"^",@"&",@"%",@"+",@"-",@"¥",@"?",@"{",@"}",@"#",@"_",@"\\",@"|",@"~",@"`",@"∑",@"€",@"£",@"。"];
    }
    return _symbolArray;
}

- (void)addControl{
    NSMutableArray *btnArray = [NSMutableArray array];
    for (int i = 0; i < 30; i++) {
        FBYCustomKeyBordButton *btn = [FBYCustomKeyBordButton buttonWithTitle:self.symbolArray[i] tag:i delegate:self];
        [btn addTarget:self action:@selector(btnTouchDown:) forControlEvents:(UIControlEventTouchDown)];
        [btn addTarget:self action:@selector(btnTouchCancel:) forControlEvents:(UIControlEventTouchUpInside)];
        [btn addTarget:self action:@selector(btnTouchCancel:) forControlEvents:(UIControlEventTouchUpOutside)];
        [btn addTarget:self action:@selector(btnTouchCancel:) forControlEvents:(UIControlEventTouchCancel)];
        [self addSubview:btn];
        [btnArray addObject:btn];
    }
}
9. 新建FBYCustomKeyBord类,实现键盘类型切换功能

FBYCustomKeyBord类中根据JS调用键盘时传入的参数,来实现何种键盘模式,实现键盘类型,共有6种类型:数字及字母、字母及数字、数字及字母特殊字符、字母及数字特殊字符、仅数字、仅字母。
键盘视图显示类型,共包括5种类型:普通、文本框、密码、支付密码格、无标题。
核心代码如下:

-(void)setKeybordType:(FBYCustomKeyBordType)keybordType{
    _keybordType=keybordType;
    [self.numPad removeFromSuperview];
    if(_keybordType==FBYCustomKeyBordType_NumWord){
        self.numPad.random=self.random;
        self.numPad.delegate=self;
        [self addSubview:self.numPad];
    }else if(_keybordType==FBYCustomKeyBordType_WordNum){
        self.wordPad.random=self.random;
        self.wordPad.delegate=self;
        [self addSubview:self.wordPad];
    }else if(_keybordType==FBYCustomKeyBordType_Num){
        self.numOnlyPad.random=self.random;
        self.numOnlyPad.delegate=self;
        [self addSubview:self.numOnlyPad];
    }else if(_keybordType==FBYCustomKeyBordType_NumWordSymbol){
        self.numPad.random=self.random;
        self.numPad.delegate=self;
        [self addSubview:self.numPad];
    }else if(_keybordType==FBYCustomKeyBordType_Word){
        self.wordPad.random=self.random;
        self.wordPad.delegate=self;
        [self addSubview:self.wordPad];
    }else if (keybordType==FBYCustomKeyBordType_WordNumSymbol){
        self.wordPad.random=self.random;
        self.wordPad.delegate=self;
        [self addSubview:self.wordPad];
    }
}
10. 实现根据密码判断密码强度和长度功能

根据密码字符串获取其长度,代码如下:

//FBYCustomKeyBord.m
#pragma mark 长度计算
-(NSUInteger)messageLength:(NSString *)message{
    NSString *msg=[message copy];
    
    NSUInteger length= msg.length;
    NSLog(@"%lu",(unsigned long)length);
    return length;
}

根据密码字符串message,通过正则校验,判断字符串中包含几种字符,进而判断其密码强度。
总共是数字、大写字母、小写字母、特殊字符四种状态,包含两种强度为弱,包含三种强度为中,包含四种强度为强,代码如下:

//FBYCustomKeyBord.m
#pragma mark 强度计算
-(NSUInteger)messageStrength:(NSString *)message{
    NSString *msg=[message copy];
    NSUInteger length= msg.length;
    BOOL capitalBool = NO;
    BOOL lowercaseBool = NO;
    BOOL numberBool = NO;
    BOOL stringBool = NO;
    NSString* result1;
    NSString* result2;
    NSString* result3;
    NSString* result4;
    for (int i = 0; i < length; i++) {
        char commitChar = [msg characterAtIndex:i];
        if((commitChar>64)&&(commitChar<91)){
            NSLog(@"字符串中含有大写英文字母");
            capitalBool = YES;
        }else if((commitChar>96)&&(commitChar<123)){
            NSLog(@"字符串中含有小写英文字母");
            lowercaseBool = YES;
        }else if((commitChar>47)&&(commitChar<58)){
            NSLog(@"字符串中含有数字");
            numberBool = YES;
        }else{
            NSLog(@"字符串中含有空格");
            stringBool = YES;
        }
    }
    result1 = [NSString stringWithFormat:@"%d",capitalBool];
    result2 = [NSString stringWithFormat:@"%d",lowercaseBool];
    result3 = [NSString stringWithFormat:@"%d",numberBool];
    result4 = [NSString stringWithFormat:@"%d",stringBool];
    
    NSMutableArray* resultArray = [[NSMutableArray alloc] init];
    [resultArray addObject:[NSString stringWithFormat:@"%@",result1]];
    [resultArray addObject:[NSString stringWithFormat:@"%@",result2]];
    [resultArray addObject:[NSString stringWithFormat:@"%@",result3]];
    [resultArray addObject:[NSString stringWithFormat:@"%@",result4]];
    int intResult=0;
    for (int j=0; j<[resultArray count]; j++)
    {
        if ([[resultArray objectAtIndex:j] isEqualToString:@"1"])
        {
            intResult++;
        }
    }
    NSUInteger result;
    if (intResult == 4){
        result = 3;
    }else if (intResult == 3){
        result = 2;
    }else if (intResult == 2){
        result = 1;
    }else{
        result = 0;
    }
    return result;
}
11. 实现输出密码SM3加密功能

这里的密码加密采用的是国密SM3加密方式,代码如下:

#pragma mark 加密设置
-(NSString *)encryptMessage:(NSString *)message{
    NSString *msg=[message copy];
    return [self sm3:msg];
}

#pragma mark - 对字符串做sm3处理
- (NSString *) sm3:(NSString *) input
{
    NSData *inputData = [input dataUsingEncoding:NSUTF8StringEncoding];
    NSData *outputData = [CustomKBSM3Coded sm3_hashWithPainData:inputData];
    //NSString *outputString = [GTMBase64 stringByEncodingData:outputData];
    NSString *outputString = [self convertDataToHexStr:outputData];
    NSString *upper = [outputString uppercaseString];
    return upper;
}
12. 根据传参打开浏览器

此浏览器插件支持打开自定义浏览器和打开默认浏览器,具体使用哪种方法打开浏览器,需要JavaScript通过arguments字典以字段的形式传过来,这里就使用openType字段。

// CustomKeyboard.m
#import "CustomKeyboard.h"
#import <React/RCTUtils.h>
@interface CustomKeyboard ()<FBYCustomKeyBordDelegate>
@property(strong,nonatomic)RCTResponseSenderBlock sucessCallback;
@property(strong,nonatomic)RCTResponseSenderBlock failCallback;
@property (nonatomic, strong) FBYCustomKeyBord *keyBoard;
@property(assign,nonatomic)FBYCustomKeyBordType keybordType;
@property(assign,nonatomic)FBYCustomKeyBordShowType keybordShowType;
@property(strong,nonatomic)NSString *tag;
@property(strong,nonatomic)NSString *isUp;
@end
@implementation CustomKeyboard
RCT_EXPORT_MODULE(KeybordPlugin);
RCT_EXPORT_METHOD(open:(NSDictionary *)arguments
                  withCompletionHandler:(RCTResponseSenderBlock)completion
                  failureHandler:(RCTResponseSenderBlock)failure)
{
    dispatch_async(dispatch_get_main_queue(), ^{
        self.keyBoard = [FBYCustomKeyBord instance];
        self.keyBoard.delegate = self;
        self.sucessCallback = sucessCallback;
        self.failCallback =  failCallback;
        NSString *isUp=@"1";
        NSString *isRandom=@"0";
        NSString *type=@"4";
        NSString *showType=@"0";
        NSString *isEncrypt=@"0";
        //是否是随机键盘
        self.keyBoard.random = YES;
        self.keybordType = FBYCustomKeyBordType_Num;   
        self.keybordShowType = FBYCustomKeyBordShowType_Common;     
        self.keyBoard.keybordType = self.keybordType;
        //弹起键盘或收起键盘
        self.keyBoard.keybordShowType = self.keybordShowType;
        dispatch_async(dispatch_get_main_queue(), ^{
            if ((isUp==nil) || isUp.intValue == 1) {
                [self.keyBoard popKeyBordInParent:RCTPresentedViewController()];
            } else {
                [self.keyBoard disappearSwitchBtnClickWithBlock:^{
                    self.sucessCallback(@[@{SucessReslutCode:@"1",SucessData:@"ok"}]);
                    NSLog(@"成功调起密码键盘方法");
                }]; 
            }
        });
    });
}
//键盘数据回调
-(void)customKeybord:(FBYCustomKeyBord *)keybord didReturnMessage:(NSString *)message withLength:(NSUInteger)length withStrength:(NSUInteger)strength{
    if(self.tag == nil){
        self.tag = [CustomKeyboard getSecondTimeStringSince1970];
    }
    if (![self.isUp isEqualToString:@"0"]) {
        self.sucessCallback(@[@{SucessReslutCode:@"1",SucessData:@{@"pwdLength":[NSString stringWithFormat:@"%lu",(unsigned long)length],@"pwdStrong":[NSString stringWithFormat:@"%lu",strength],@"pwdValue":message}}]);
        NSLog(@"成功调起密码键盘方法");
    }
}

13. Javascript调用浏览器方法

现在从 Javascript 里可以这样调用这个方法:

import { NativeModules } from "react-native";
const CustomkeyBoardPlugin = NativeModules.KeybordPlugin;
CustomkeyBoardPlugin.onKeyboard({isRandom:"1",isUp:"1",type:"4",showType:"3"},(msg) => {
                                         Alert.alert(JSON.stringify(msg));
                                         },(err) => {
                                         Alert.alert(JSON.stringify(err));
                                         });

希望可以帮助大家,如有问题可加QQ技术交流群: 668562416

如果哪里有什么不对或者不足的地方,还望读者多多提意见或建议

如需转载请联系我,经过授权方可转载,谢谢

本篇已同步到个人博客:FBY展菲

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,558评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,002评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,036评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,024评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,144评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,255评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,295评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,068评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,478评论 1 305
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,789评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,965评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,649评论 4 336
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,267评论 3 318
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,982评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,223评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,800评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,847评论 2 351

推荐阅读更多精彩内容

  • 1、通过CocoaPods安装项目名称项目信息 AFNetworking网络请求组件 FMDB本地数据库组件 SD...
    阳明先生_X自主阅读 15,975评论 3 119
  • 完美的世界,结局并不完美,还带有悲伤的色彩。当纸币从菲利普破洞的圣诞节服装洒落到布奇身边;当那小小男孩手里紧紧攥着...
    随云说阅读 887评论 0 0
  • 晏燚阅读 233评论 0 0
  • 曾经 我们都以为只要坚强自己的选择 我们就可以一路守护彼此 曾经 我们都以为能接受大家的性格 我们就可以快快乐乐的...
    午夜_倾诉阅读 258评论 0 3