iOS开发实用技巧—身份证的正则校验 -电脑资料

电脑资料 时间:2019-01-01 我要投稿
【www.unjs.com - 电脑资料】

    说明:

    在ios项目的开发中可能很多地方都需要用到身份证校验,一般在开发的时候很多人都是直接百度去网上荡相关的正则表达式和校验代码,但是网上疯狂粘贴复制的校验代码本身也可能并不准确,可能会有风险,比如2013年1月1号起停止使用15位的身份证,网上的身份证校验普遍支持15位的号码,

iOS开发实用技巧—身份证的正则校验

    在开发过程中,进行类似处理的时候,还是需要一些甄别的能力的,当然也要考虑自己的项目的实际情况。该文贴出了最近项目中使用到得身份证校验代码,以方便有需要的人“谨慎”获取。

    一、规则

    下面是iOS身份证校验规则,对于第6点就值得商榷,按道理出生年份前两位是20也应该是合理的。如果要校验投保人需要年满18岁,需要另行检查,不应放在身份证校验里面。

    长度必须是18位,前17位必须是数字,第十八位可以是数字或X(校验时不区分大小写)

    前两位必须是以下35种情形中的一种: 11,12,13,14,15,21,22,23,31,32,33,34,35,36,37,41,42,43,44,45,46,50,51,52,53,54,61,62,63,64,65,71,81,82,91

    第7到第14位出生年月日。第7到第10位为出生年份;11到12位表示月份,范围为01~12;13到14位为合法的日期,比如月份是04,范围应是01~30

    第17位表示性别,必须是0或1,0表示女,1表示男

    第18位为前17位的校验位 算法如下:

    总和 = (n1 + n11) * 7 + (n2 + n12) * 9 + (n3 + n13) * 10 + (n4 + n14) * 5 + (n5 + n15) * 8 + (n6 + n16) * 4 + (n7 + n17) * 2 + n8 + n9 * 6 + n10 * 3,其中n1表示1位数字,其它类似

    用总和除以11,看余数是多少, 余数只可能有0 1 2 3 4 5 6 7 8 9 10这11个数字。其分别对应的最后一位身份证的号码为1 0 X 9 8 7 6 5 4 3 2

    第7位必须为1,第8位必须为9,即:出生年份的前两位必须是19

    二、代码示例:

    对于这种需要在很多地方都用到的代码,可以使用一个工具类或者是分类来写。这里把校验的代码写在了一个工具类中。

    VerifyRegexTool.h文件代码:

    1 #import

    2

    3 @interface VerifyRegexTool : NSObject

    4

    5 + (BOOL)verifyIsNotEmpty:(NSString *)str; //验证是否不为空

    6

    7 + (BOOL)verifyText:(NSString *)text withRegex:(NSString *)regex;  //正则验证

    8

    9 + (BOOL)verifyIDCardNumber:(NSString *)value; //验证身份证

    10

    11 + (BOOL)verifyCardNumberWithSoldier:(NSString *)value; //验证军官证或警官证

    12

    13 + (BOOL)verifyIDCardHadAdult:(NSString *)card; //验证身份证是否成年且小于100岁****这个方法中不做身份证校验,请确保传入的是正确身份证

    14

    15 + (BOOL)verifyIDCardMoreThanPointDate:(NSString *)card withNumber:(NSInteger)number withAddTimeInterval:(NSTimeInterval)interval withDateType:(DateType)dateType; //验证身份证加上指定天数是否大于指定number的类型

    16

    17 + (BOOL)verifyIDCardLessThanPointDate:(NSString *)card withNumber:(NSInteger)number withAddTimeInterval:(NSTimeInterval)interval withDateType:(DateType)dateType; //验证身份证是否小于指定number的类型

    18

    19

    20 + (NSString *)getIDCardBirthday:(NSString *)card; //得到身份证的生日****这个方法中不做身份证校验,请确保传入的是正确身份证

    21 + (NSInteger)getIDCardSex:(NSString *)card; //得到身份证的性别(1男0女)****这个方法中不做身份证校验,请确保传入的是正确身份证

    22

    23 @end

    VerifyRegexTool.m文件代码:

    1 #import "VerifyRegexTool.h"

    2

    3 @implementation VerifyRegexTool

    4

    5 //验证是否不为空

    6 + (BOOL)verifyIsNotEmpty:(NSString *)str

    7 {

    8  if (!str) return NO;

    9

    10  str = [str stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];

    11  if (![str isEqualToString:@""]) {

    12    return YES;

    13  } else {

    14    return NO;

    15  }

    16 }

    17

    18 //正则验证

    19 + (BOOL)verifyText:(NSString *)text withRegex:(NSString *)regex

    20 {

    21  return [[text stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]] isMatchedByRegex:regex];

    22 }

    23

    24 //验证身份证

    25 //必须满足以下规则

    26 //1. 长度必须是18位,前17位必须是数字,第十八位可以是数字或X

    27 //2. 前两位必须是以下情形中的一种:11,12,13,14,15,21,22,23,31,32,33,34,35,36,37,41,42,43,44,45,46,50,51,52,53,54,61,62,63,64,65,71,81,82,91

    28 //3. 第7到第14位出生年月日。第7到第10位为出生年份;11到12位表示月份,范围为01-12;13到14位为合法的日期

    29 //4. 第17位表示性别,双数表示女,单数表示男

    30 //5. 第18位为前17位的校验位

    31 //算法如下:

    32 //(1)校验和 = (n1 + n11) * 7 + (n2 + n12) * 9 + (n3 + n13) * 10 + (n4 + n14) * 5 + (n5 + n15) * 8 + (n6 + n16) * 4 + (n7 + n17) * 2 + n8 + n9 * 6 + n10 * 3,其中n数值,表示第几位的数字

    33 //(2)余数 = 校验和 % 11

    34 //(3)如果余数为0,校验位应为1,余数为1到10校验位应为字符串“0X98765432”(不包括分号)的第余数位的值(比如余数等于3,校验位应为9)

    35 //6. 出生年份的前两位必须是19或20

    36 + (BOOL)verifyIDCardNumber:(NSString *)value

    37 {

    38  value = [value stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];

    39  if ([value length] != 18) {

    40    return NO;

    41  }

    42  NSString *mmdd = @"(((0[13578]|1[02])(0[1-9]|[12][0-9]|3[01]))|((0[469]|11)(0[1-9]|[12][0-9]|30))|(02(0[1-9]|[1][0-9]|2[0-8])))";

    43  NSString *leapMmdd = @"0229";

    44  NSString *year = @"(19|20)[0-9]{2}";

    45  NSString *leapYear = @"(19|20)(0[48]|[2468][048]|[13579][26])";

    46  NSString *yearMmdd = [NSString stringWithFormat:@"%@%@", year, mmdd];

    47  NSString *leapyearMmdd = [NSString stringWithFormat:@"%@%@", leapYear, leapMmdd];

    48  NSString *yyyyMmdd = [NSString stringWithFormat:@"((%@)|(%@)|(%@))", yearMmdd, leapyearMmdd, @"20000229"];

    49  NSString *area = @"(1[1-5]|2[1-3]|3[1-7]|4[1-6]|5[0-4]|6[1-5]|82|[7-9]1)[0-9]{4}";

    50  NSString *regex = [NSString stringWithFormat:@"%@%@%@", area, yyyyMmdd , @"[0-9]{3}[0-9Xx]"];

    51

    52  NSPredicate *regexTest = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", regex];

    53  if (![regexTest evaluateWithObject:value]) {

    54    return NO;

    55  }

    56  int summary = ([value substringWithRange:NSMakeRange(0,1)].intValue + [value substringWithRange:NSMakeRange(10,1)].intValue) *7

    57      + ([value substringWithRange:NSMakeRange(1,1)].intValue + [value substringWithRange:NSMakeRange(11,1)].intValue) *9

    58      + ([value substringWithRange:NSMakeRange(2,1)].intValue + [value substringWithRange:NSMakeRange(12,1)].intValue) *10

    59      + ([value substringWithRange:NSMakeRange(3,1)].intValue + [value substringWithRange:NSMakeRange(13,1)].intValue) *5

    60      + ([value substringWithRange:NSMakeRange(4,1)].intValue + [value substringWithRange:NSMakeRange(14,1)].intValue) *8

    61      + ([value substringWithRange:NSMakeRange(5,1)].intValue + [value substringWithRange:NSMakeRange(15,1)].intValue) *4

    62      + ([value substringWithRange:NSMakeRange(6,1)].intValue + [value substringWithRange:NSMakeRange(16,1)].intValue) *2

    63      + [value substringWithRange:NSMakeRange(7,1)].intValue *1 + [value substringWithRange:NSMakeRange(8,1)].intValue *6

    64      + [value substringWithRange:NSMakeRange(9,1)].intValue *3;

    65  NSInteger remainder = summary % 11;

    66  NSString *checkBit = @"";

    67  NSString *checkString = @"10X98765432";

    68  checkBit = [checkString substringWithRange:NSMakeRange(remainder,1)];// 判断校验位

    69  return [checkBit isEqualToString:[[value substringWithRange:NSMakeRange(17,1)] uppercaseString]];

    70 }

    71

    72 //验证军官证或警官证

    73 //必须是下面两种格式中的一种

    74 //格式一:4到20位数字

    75 //格式二:大于或等于10位并且小于等于20位(中文按两位),并满足以下规则

    76 //1)必须有“字第”两字

    77 //2)“字第”前面有至少一个字符

    78 //3)“字第”后是4位以上数字

    79 + (BOOL)verifyCardNumberWithSoldier:(NSString *)value

    80 {

    81  NSString *s1 = @"^\\d*$";

    82  NSString *s2 = @"^.{1,}字第\\d{4,}$";

    83  //NSString *s3 = @"^([A-Za-z0-9\\u4e00-\\u9fa5])*$";

    84  value = [value stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];

    85  if ([VerifyRegexTool verifyText:value withRegex:s1]) {

    86    NSString *s11 = @"^\\d{4,20}$";

    87    return [value isMatchedByRegex:s11];

    88  } else if ([self lengthUsingChineseCharacterCountByTwo:value] >= 10

    89        && [self lengthUsingChineseCharacterCountByTwo:value] <= 20) {

    90    return [value isMatchedByRegex:s2];

    91  }

    92

    93  return NO;

    94 }

    95

    96 + (NSUInteger)lengthUsingChineseCharacterCountByTwo:(NSString *)string{

    97  NSUInteger count = 0;

    98  for (NSUInteger i = 0; i< string.length; ++i) {

    99    if ([string characterAtIndex:i] < 256) {

    100      count++;

    101    } else {

    102      count += 2;

    103    }

    104  }

    105  return count;

    106 }

    107

    108 //验证身份证是否成年且小于100岁****这个方法中不做身份证校验,请确保传入的是正确身份证

    109 + (BOOL)verifyIDCardHadAdult:(NSString *)card

    110 {

    111  NSString *birtday = [VerifyRegexTool getIDCardBirthday:card]; //****年**月**日

    112  //转换为****-**-**

    113  birtday = [birtday stringByReplacingOccurrencesOfString:@"年" withString:@"-"];

    114  birtday = [birtday stringByReplacingOccurrencesOfString:@"月" withString:@"-"];

    115  birtday = [birtday stringByReplacingOccurrencesOfString:@"日" withString:@""];

    116  birtday = [NSString stringWithFormat:@"%@ 00:00",birtday];

    117  NSDate *dateBirtday = [NSDate dateFromString:birtday];

    118  NSInteger year = [[NSDate date] getIntervalTime:dateBirtday withDateType:DateTypeYear]; //得到年数

    119

    120  if (year >= 18 && year < 100) {

    121    return YES;

    122  } else {

    123    return NO;

    124  }

    125

    126 }

    127

    128 //验证身份证加上指定天数是否大于指定number的类型

    129 + (BOOL)verifyIDCardMoreThanPointDate:(NSString *)card withNumber:(NSInteger)number withAddTimeInterval:(NSTimeInterval)interval withDateType:(DateType)dateType {

    130  NSString *birtday = [VerifyRegexTool getIDCardBirthday:card]; //****年**月**日

    131  //转换为****-**-**

    132  birtday = [birtday stringByReplacingOccurrencesOfString:@"年" withString:@"-"];

    133  birtday = [birtday stringByReplacingOccurrencesOfString:@"月" withString:@"-"];

    134  birtday = [birtday stringByReplacingOccurrencesOfString:@"日" withString:@""];

    135  birtday = [NSString stringWithFormat:@"%@ 00:00",birtday];

    136  NSDate *dateBirtday = [NSDate dateFromString:birtday];

    137  NSDate *today = [NSDate dateFromStringWithoutTime:[[NSDate date] strDate]];

    138  NSDate *pointDate = [today dateByAddingTimeInterval:interval];

    139

    140  //tempDate为number后的日期

    141  NSDate *tempDate = [pointDate dateAddNumber:-number withDateType:dateType]; //临界日期

    142  if ([dateBirtday earlierDate:tempDate] == dateBirtday) { //如果生日+指定天数大雨tempdate,则通过

    143    return YES;

    144  } else {

    145    return NO;

    146  }

    147 }

    148

    149 //验证身份证加上指定天数是否小于指定number的类型

    150 + (BOOL)verifyIDCardLessThanPointDate:(NSString *)card withNumber:(NSInteger)number withAddTimeInterval:(NSTimeInterval)interval withDateType:(DateType)dateType

    151 {

    152  NSString *birtday = [VerifyRegexTool getIDCardBirthday:card]; //****年**月**日

    153  //转换为****-**-**

    154  birtday = [birtday stringByReplacingOccurrencesOfString:@"年" withString:@"-"];

    155  birtday = [birtday stringByReplacingOccurrencesOfString:@"月" withString:@"-"];

    156  birtday = [birtday stringByReplacingOccurrencesOfString:@"日" withString:@""];

    157  birtday = [NSString stringWithFormat:@"%@ 00:00",birtday];

    158  NSDate *dateBirtday = [NSDate dateFromString:birtday];

    159  NSDate *today = [NSDate dateFromStringWithoutTime:[[NSDate date] strDate]];

    160  NSDate *pointDate = [today dateByAddingTimeInterval:interval];

    161

    162  //tempDate为number后的日期

    163  NSDate *tempDate = [pointDate dateAddNumber:-number withDateType:dateType]; //临界日期

    164  if ([tempDate earlierDate:dateBirtday] == tempDate) { //如果生日+指定天数小于tempdate,则通过

    165    return YES;

    166  } else {

    167    return NO;

    168  }

    169 }

    170

    171 //得到身份证的生日****这个方法中不做身份证校验,请确保传入的是正确身份证

    172 + (NSString *)getIDCardBirthday:(NSString *)card {

    173  card = [card stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];

    174  if ([card length] != 18) {

    175    return nil;

    176  }

    177  NSString *birthady = [NSString stringWithFormat:@"%@年%@月%@日",[card substringWithRange:NSMakeRange(6,4)], [card substringWithRange:NSMakeRange(10,2)], [card substringWithRange:NSMakeRange(12,2)]];

    178  return birthady;

    179 }

    180

    181 //得到身份证的性别(1男0女)****这个方法中不做身份证校验,请确保传入的是正确身份证

    182 + (NSInteger)getIDCardSex:(NSString *)card {

    183  card = [card stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];

    184  NSInteger defaultValue = 0;

    185  if ([card length] != 18) {

    186    return defaultValue;

    187  }

    188  NSInteger number = [[card substringWithRange:NSMakeRange(16,1)] integerValue];

    189  if (number % 2 == 0) { //偶数为女

    190    return 0;

    191  } else {

    192    return 1;

    193  }

    194 }

    195

    196 @end

    身份证校验调用示例:

    1  if (![VerifyRegexTool verifyIDCardNumber:self.IdentityCardNOTextfield.text]) { //验证身份证是否真实

    2    [self showMessageHUD:@"请输入正确的身份证号码!" withTimeInterval:kShowMessageTime];

    3    return;

    4  }

最新文章