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

正则定义 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; } } }

【iOS|iOS 手机号、固话、身份证号等验证总结】注释:
^1匹配输入字符串开始的位置是;
第二位和第三位判断:([358][0-9]|4[579]|66|7[0135678]|9[89]) 。其中 [358][0-9]表示匹配第二位为或者或者第三位为任意数字;4[579]表示第二位为第三位为或者或者; 66表示第二位为第三位为。以此类推应当明白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 -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 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; }

    推荐阅读