美文网首页ios开发那些事 Objective - C 开发那些事
iOS 手机号、固话、身份证号等验证总结

iOS 手机号、固话、身份证号等验证总结

作者: 没有昵称的昵称没有 | 来源:发表于2019-07-17 18:01 被阅读31次
    正则定义

    iOS开发经常需要验证某一事物是否正确,而我们为了验证其正确性就会用到正则表达式(regular expression)其定义是一个描述字符模式的对象。也是一种规则,我们通过这种规则来进行字符串的检索、判断、替换等工作。以下是我们开发时遇到的验证需求,特以此文做笔记。若有错误请告知!

    1、手机号验证:
    /**
     *  判断手机号是否正确
     */
    + (BOOL)valiMobile:(NSString *)mobile{
        mobile = [mobile stringByReplacingOccurrencesOfString:@" " withString:@""];
        if (mobile.length != 11)
        {
            return NO;
        }else{
            NSString * PHONE_NUM = @"^1([358][0-9]|4[579]|66|7[0135678]|9[89])[0-9]{8}$";
            NSPredicate *pred = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", PHONE_NUM];
            BOOL isMatch = [pred evaluateWithObject:mobile];
            if (isMatch) {
                return YES;
            }else{
                return NO;
            }
        }
    }
    

    注释:
    ^1匹配输入字符串开始的位置是\color{red}{1};
    第二位和第三位判断:([358][0-9]|4[579]|66|7[0135678]|9[89]) 。其中 [358][0-9]表示匹配第二位为\color{red}{3}或者\color{red}{5}或者\color{red}{8}第三位为任意数字;4[579]表示第二位为\color{red}{4}第三位为\color{red}{5}或者\color{red}{7}或者\color{red}{9};66表示第二位为\color{red}{6}第三位为\color{red}{6}。以此类推应当明白7[0135678]9[89]
    [0-9]{8}$表示匹配8次0到9的数字,即后8位须为数字。
    若有新号段可根据注释说明添加判断

    2、大陆地区固话验证:
    /**
     * 大陆地区固话
     * 号码:七位或八位
     */
    + (BOOL)isFixedTelephone:(NSString *)phoneNum {
        //去除"-"、"()"、"()"按格式样式去除
        phoneNum = [phoneNum stringByReplacingOccurrencesOfString:@"-" withString:@""];
        phoneNum = [phoneNum stringByReplacingOccurrencesOfString:@"(" withString:@""];
        phoneNum = [phoneNum stringByReplacingOccurrencesOfString:@")" withString:@""];
        phoneNum = [phoneNum stringByReplacingOccurrencesOfString:@"(" withString:@""];
        phoneNum = [phoneNum stringByReplacingOccurrencesOfString:@")" withString:@""];
        NSString * FT = @"^0(10|2[0-5789]|\\d{3})\\d{7,8}$";
        NSPredicate *regextestcm = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", FT];
        return [regextestcm evaluateWithObject:phoneNum];
    }
    

    注释:
    ^匹配输入字符串开始的位置
    \d匹配一个数字字符,等价于[0-9]。
    {n,m}至少匹配n次,最多匹配m次,尽可能多的匹配。n和m均为非负整数,且n<=m。
    $匹配输入字符串结尾的位置

    3、身份证号验证:
    /**
     * 身份证号段正则表达式
     */
    + (BOOL)judgeIdentityStringValid:(NSString *)identityString {
        if (identityString.length != 18) return NO;
        // 正则表达式判断基本 身份证号是否满足格式
        NSString *regex2 = @"^(^[1-9]\\d{7}((0\\d)|(1[0-2]))(([0|1|2]\\d)|3[0-1])\\d{3}$)|(^[1-9]\\d{5}[1-9]\\d{3}((0\\d)|(1[0-2]))(([0|1|2]\\d)|3[0-1])((\\d{4})|\\d{3}[Xx])$)$";
        NSPredicate *identityStringPredicate = [NSPredicate predicateWithFormat:@"SELF MATCHES %@",regex2];
        //如果通过该验证,说明身份证格式正确,但准确性还需计算
        if(![identityStringPredicate evaluateWithObject:identityString]) return NO;
        //** 开始进行校验 *//
        //将前17位加权因子保存在数组里
        NSArray *idCardWiArray = @[@"7", @"9", @"10", @"5", @"8", @"4", @"2", @"1", @"6", @"3", @"7", @"9", @"10", @"5", @"8", @"4", @"2"];
        //这是除以11后,可能产生的11位余数、验证码,也保存成数组
        NSArray *idCardYArray = @[@"1", @"0", @"10", @"9", @"8", @"7", @"6", @"5", @"4", @"3", @"2"];
        //用来保存前17位各自乖以加权因子后的总和
        NSInteger idCardWiSum = 0;
        for(int i = 0;i < 17;i++) {
            NSInteger subStrIndex  = [[identityString substringWithRange:NSMakeRange(i, 1)] integerValue];
            NSInteger idCardWiIndex = [[idCardWiArray objectAtIndex:i] integerValue];
            idCardWiSum      += subStrIndex * idCardWiIndex;
        }
        //计算出校验码所在数组的位置
        NSInteger idCardMod=idCardWiSum%11;
        //得到最后一位身份证号码
        NSString *idCardLast= [identityString substringWithRange:NSMakeRange(17, 1)];
        //如果等于2,则说明校验码是10,身份证号码最后一位应该是X
        if(idCardMod==2) {
            if(![idCardLast isEqualToString:@"X"]||[idCardLast isEqualToString:@"x"]) {
                return NO;
            }
        }else{
            //用计算出的验证码与最后一位身份证号码匹配,如果一致,说明通过,否则是无效的身份证号码
            if(![idCardLast isEqualToString: [idCardYArray objectAtIndex:idCardMod]]) {
                return NO;
            }
        }
        return YES;
    }
    
    4、银行卡号有效性问题Luhn算法:

    现行 16 位银联卡现行卡号开头 6 位是 622126~622925 之间的,7 到 15 位是银行自定义的,以下为判断点:

    • 可能是发卡分行,发卡网点,发卡序号,第 16 位是校验码。
    • 16 位卡号校验位采用 Luhm 校验方法计算:
    • 1.将未带校验位的 15 位卡号从右依次编号 1 到 15,位于奇数位号上的数字乘以 2
    • 2.将奇位乘积的个十位全部相加,再加上所有偶数位上的数字
    • 3.将加法和加上校验位能被 10 整除。
    /** 
     *银行卡号有效性问题Luhn算法
     */
    + (BOOL)isBankCard:(NSString *)cardNum {
        if (cardNum.length == 0) {
            return NO;
        }
        NSString * lastNum = [[cardNum substringFromIndex:(cardNum.length - 1)] copy];//取出最后一位
        NSString * forwardNum = [[cardNum substringToIndex:(cardNum.length -1)]copy];//前15或18位
        NSMutableArray * forwardArr = [[NSMutableArray alloc] initWithCapacity:0];
        for (int i=0; i<forwardNum.length; i++) {
            NSString * subStr = [forwardNum substringWithRange:NSMakeRange(i,1)];
            [forwardArr addObject:subStr];
        }
        NSMutableArray * forwardDescArr = [[NSMutableArray alloc] initWithCapacity:0];
        for (int i = (int)(forwardArr.count-1); i> -1; i--) {
            //前15位或者前18位倒序存进数组
            [forwardDescArr addObject:forwardArr[i]];
        }
        NSMutableArray * arrOddNum = [[NSMutableArray alloc] initWithCapacity:0];//奇数位*2的积 < 9
        NSMutableArray * arrOddNum2 = [[NSMutableArray alloc] initWithCapacity:0];//奇数位*2的积 > 9
        NSMutableArray * arrEvenNum = [[NSMutableArray alloc] initWithCapacity:0];//偶数位数组
        for (int i=0; i< forwardDescArr.count; i++) {
            NSInteger num = [forwardDescArr[i] intValue];
            if (i%2) {
                //偶数位
                [arrEvenNum addObject:[NSNumber numberWithInteger:num]];
            }else{
                //奇数位
                if (num *2 < 9) {
                    [arrOddNum addObject:[NSNumber numberWithInteger:num *2]];
                }else{
                    NSInteger decadeNum = (num *2) / 10;
                    NSInteger unitNum = (num *2) % 10;
                    [arrOddNum2 addObject:[NSNumber numberWithInteger:unitNum]];
                    [arrOddNum2 addObject:[NSNumber numberWithInteger:decadeNum]];
                }
            }
        }
        __block NSInteger sumOddNumTotal = 0;
        [arrOddNum enumerateObjectsUsingBlock:^(NSNumber * obj,NSUInteger idx, BOOL *stop) {
            sumOddNumTotal += [obj integerValue];
        }];
        __block NSInteger sumOddNum2Total = 0;
        [arrOddNum2 enumerateObjectsUsingBlock:^(NSNumber * obj,NSUInteger idx, BOOL *stop) {
            sumOddNum2Total += [obj integerValue];
        }];
        __block NSInteger sumEvenNumTotal =0 ;
        [arrEvenNum enumerateObjectsUsingBlock:^(NSNumber * obj,NSUInteger idx, BOOL *stop) {
            sumEvenNumTotal += [obj integerValue];
        }];
        NSInteger lastNumber = [lastNum integerValue];
        NSInteger luhmTotal = lastNumber + sumEvenNumTotal + sumOddNum2Total + sumOddNumTotal;
        return (luhmTotal%10 ==0)?YES:NO;
    }
    

    该判断亲测满足大部分银行卡验证,如有不全,请自行添加判断。

    5 、车牌号码验证
    /**
     * 车牌号码正则表达式
     */
    +(BOOL)checkCarID:(NSString *)carID {
        if (carID.length==7) {
            //普通汽车,7位字符,不包含I和O,避免与数字1和0混淆
            NSString *carRegex = @"^[\u4e00-\u9fa5]{1}[a-hj-np-zA-HJ-NP-Z]{1}[a-hj-np-zA-HJ-NP-Z0-9]{4}[a-hj-np-zA-HJ-NP-Z0-9\u4e00-\u9fa5]$";
            NSPredicate *carTest = [NSPredicate predicateWithFormat:@"SELF MATCHES %@",carRegex];
            return [carTest evaluateWithObject:carID];
        }else if(carID.length==8){
            //新能源车,8位字符,第一位:省份简称(1位汉字),第二位:发牌机关代号(1位字母);
            //小型车,第三位:只能用字母D或字母F,第四位:字母或者数字,后四位:必须使用数字;([DF][A-HJ-NP-Z0-9][0-9]{4})
            //大型车3-7位:必须使用数字,后一位:只能用字母D或字母F。([0-9]{5}[DF])
            NSString *carRegex = @"^[\u4e00-\u9fa5]{1}[a-hj-np-zA-HJ-NP-Z]{1}([0-9]{5}[d|f|D|F]|[d|f|D|F][a-hj-np-zA-HJ-NP-Z0-9][0-9]{4})$";
            NSPredicate *carTest = [NSPredicate predicateWithFormat:@"SELF MATCHES %@",carRegex];
            return [carTest evaluateWithObject:carID];
        }
        return NO;
    }
    
    6 、密码验证(6-18位数字和字母组合)
    /**
     * ^ 匹配一行的开头位置
     * (?![0-9]+$) 预测该位置后面不全是数字
     * (?![a-zA-Z]+$) 预测该位置后面不全是字母
     * [0-9A-Za-z] {6,18} 由6-18位数字或这字母组成
     * $ 匹配行结尾位置
     */
    +(BOOL)checkPassword:(NSString *) password {
        NSString*pattern =@"^(?![0-9]+$)(?![a-zA-Z]+$)[a-zA-Z0-9]{6,18}";
        NSPredicate*pred = [NSPredicatepredicateWithFormat:@"SELF MATCHES %@",pattern];
        BOOL isMatch = [predevaluateWithObject:password];
        return isMatch;
    }
    

    注释:
    ?!表示正向否定预查( Negative look-ahead assertion),在任何不匹配pattern的字符串开始处匹配查找字符串。这是一个非获取匹配。

    7、邮箱验证
    /**
     判断邮箱格式是否正确的代码:
     @param email 验证的邮箱
     @return YES:正确 NO:错误
     */
    + (BOOL)isValidateEmail:(NSString *)email {
        NSString *emailRegex = @"[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,4}";
        NSPredicate *emailTest = [NSPredicate predicateWithFormat:@"SELF MATCHES%@",emailRegex];
        return [emailTest evaluateWithObject:email];
    }
    

    注释:
    [A-Za-z0-9]匹配字母数字

    8、检验是否含有特殊字符
    /**
     检验是否含有特殊字符:
     @param character 验证的字符串
     @return YES:是 NO:无
     */
    + (BOOL)isCharacter:(NSString *)character {
        NSString *CHARACTER = @"[^%&',;=?$\x22]+";
        
        NSPredicate *regextestmobile = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", CHARACTER];
        
        return [regextestmobile evaluateWithObject:character];
    }
    
    9、判断手机版本型号
    + (NSString*)iphoneType {
        
        //需要导入头文件:#import <sys/utsname.h>
        
        struct utsname systemInfo;
        
        uname(&systemInfo);
        
        NSString*platform = [NSString stringWithCString: systemInfo.machine encoding:NSASCIIStringEncoding];
        if([platform isEqualToString:@"iPhone1,1"]) return@"iPhone 2G";
        if([platform isEqualToString:@"iPhone1,2"]) return@"iPhone 3G";
        if([platform isEqualToString:@"iPhone2,1"]) return@"iPhone 3GS";
        if([platform isEqualToString:@"iPhone3,1"]) return@"iPhone 4";
        if([platform isEqualToString:@"iPhone3,2"]) return@"iPhone 4";
        if([platform isEqualToString:@"iPhone3,3"]) return@"iPhone 4";
        if([platform isEqualToString:@"iPhone4,1"]) return@"iPhone 4S";
        if([platform isEqualToString:@"iPhone5,1"]) return@"iPhone 5";
        if([platform isEqualToString:@"iPhone5,2"]) return@"iPhone 5";
        if([platform isEqualToString:@"iPhone5,3"]) return@"iPhone 5c";
        if([platform isEqualToString:@"iPhone5,4"]) return@"iPhone 5c";
        if([platform isEqualToString:@"iPhone6,1"]) return@"iPhone 5s";
        if([platform isEqualToString:@"iPhone6,2"]) return@"iPhone 5s";
        if([platform isEqualToString:@"iPhone7,1"]) return@"iPhone 6 Plus";
        if([platform isEqualToString:@"iPhone7,2"]) return@"iPhone 6";
        if([platform isEqualToString:@"iPhone8,1"]) return@"iPhone 6s";
        if([platform isEqualToString:@"iPhone8,2"]) return@"iPhone 6s Plus";
        if([platform isEqualToString:@"iPhone8,4"]) return@"iPhone SE";
        if([platform isEqualToString:@"iPhone9,1"]) return@"iPhone 7";
        if([platform isEqualToString:@"iPhone9,2"]) return@"iPhone 7 Plus";
        if([platform isEqualToString:@"iPhone10,1"]) return@"iPhone 8";
        if([platform isEqualToString:@"iPhone10,4"]) return@"iPhone 8";
        if([platform isEqualToString:@"iPhone10,2"]) return@"iPhone 8 Plus";
        if([platform isEqualToString:@"iPhone10,5"]) return@"iPhone 8 Plus";
        if([platform isEqualToString:@"iPhone10,3"]) return@"iPhone X";
        if([platform isEqualToString:@"iPhone10,6"]) return@"iPhone X";
        if([platform isEqualToString:@"iPod1,1"]) return@"iPod Touch 1G";
        if([platform isEqualToString:@"iPod2,1"]) return@"iPod Touch 2G";
        if([platform isEqualToString:@"iPod3,1"]) return@"iPod Touch 3G";
        if([platform isEqualToString:@"iPod4,1"]) return@"iPod Touch 4G";
        if([platform isEqualToString:@"iPod5,1"]) return@"iPod Touch 5G";
        if([platform isEqualToString:@"iPad1,1"]) return@"iPad 1G";
        if([platform isEqualToString:@"iPad2,1"]) return@"iPad 2";
        if([platform isEqualToString:@"iPad2,2"]) return@"iPad 2";
        if([platform isEqualToString:@"iPad2,3"]) return@"iPad 2";
        if([platform isEqualToString:@"iPad2,4"]) return@"iPad 2";
        if([platform isEqualToString:@"iPad2,5"]) return@"iPad Mini 1G";
        if([platform isEqualToString:@"iPad2,6"]) return@"iPad Mini 1G";
        if([platform isEqualToString:@"iPad2,7"]) return@"iPad Mini 1G";
        if([platform isEqualToString:@"iPad3,1"]) return@"iPad 3";
        if([platform isEqualToString:@"iPad3,2"]) return@"iPad 3";
        if([platform isEqualToString:@"iPad3,3"]) return@"iPad 3";
        if([platform isEqualToString:@"iPad3,4"]) return@"iPad 4";
        if([platform isEqualToString:@"iPad3,5"]) return@"iPad 4";
        if([platform isEqualToString:@"iPad3,6"]) return@"iPad 4";
        if([platform isEqualToString:@"iPad4,1"]) return@"iPad Air";
        if([platform isEqualToString:@"iPad4,2"]) return@"iPad Air";
        if([platform isEqualToString:@"iPad4,3"]) return@"iPad Air";
        if([platform isEqualToString:@"iPad4,4"]) return@"iPad Mini 2G";
        if([platform isEqualToString:@"iPad4,5"]) return@"iPad Mini 2G";
        if([platform isEqualToString:@"iPad4,6"]) return@"iPad Mini 2G";
        if([platform isEqualToString:@"iPad4,7"]) return@"iPad Mini 3";
        if([platform isEqualToString:@"iPad4,8"]) return@"iPad Mini 3";
        if([platform isEqualToString:@"iPad4,9"]) return@"iPad Mini 3";
        if([platform isEqualToString:@"iPad5,1"]) return@"iPad Mini 4";
        if([platform isEqualToString:@"iPad5,2"]) return@"iPad Mini 4";
        if([platform isEqualToString:@"iPad5,3"]) return@"iPad Air 2";
        if([platform isEqualToString:@"iPad5,4"]) return@"iPad Air 2";
        if([platform isEqualToString:@"iPad6,3"]) return@"iPad Pro 9.7";
        if([platform isEqualToString:@"iPad6,4"]) return@"iPad Pro 9.7";
        if([platform isEqualToString:@"iPad6,7"]) return@"iPad Pro 12.9";
        if([platform isEqualToString:@"iPad6,8"]) return@"iPad Pro 12.9";
    
        if([platform isEqualToString:@"i386"]) return@"iPhone Simulator";
        if([platform isEqualToString:@"x86_64"]) return@"iPhone Simulator";
        return platform;
    }
    

    相关文章

      网友评论

        本文标题:iOS 手机号、固话、身份证号等验证总结

        本文链接:https://www.haomeiwen.com/subject/skhqlctx.html