最近项目中碰到了这样一个需求,需要在一段文字中识别出手机号,并加上特殊颜色,和点击事件。下面说下我的思路,抛砖引玉。(如果你有更好的想法,不妨交流下)
前提是基于TTTAttributedLabel实现的。因为TTTAttributedLabel已经做了添加链接,我们目的是找出应该在哪里加链接,关于怎么加上,以及点击链接的代理事件不是本文重点。工欲善其事,必先利其器吗。(以下内容仅以国内固话和手机号为例,不涉及国外电话)
思路
主要分为两步,
-
先粗略找出字符串中可能为固话和手机号的子字符串及其在该字符串中的位置range。
什么是可能为电话号码的字符串,比如18000000000(连续11位数字),010-66666666(3位区号-8位号码)还有(3-7,4-8,4-7)以及区号和号码之间不用“-”的,这些都是有可能为电话号码的。
用正则表达式表示就是#define PHONEREGULAR @"\\d{3,4}[- ]?\\d{7,8}"//匹配10到12位连续数字,或者带连字符/空格的固话号,空格和连字符可以省略。
关于正则表达式这里有篇30分钟入门教程
核心代码实现
self.ddLabel.text = tempStr;
NSRange stringRange = NSMakeRange(0, tempStr.length);
//正则匹配
NSError *error;
NSRegularExpression *regexps = [NSRegularExpression regularExpressionWithPattern:PHONEREGULAR options:0 error:&error];
if (!error && regexps != nil) {
[regexps enumerateMatchesInString:[tempStr string] options:0 range:stringRange usingBlock:^(NSTextCheckingResult * _Nullable result, NSMatchingFlags flags, BOOL * _Nonnull stop) {
//可能为电话号码的字符串及其所在位置
NSString *actionString = [NSString stringWithFormat:@"%@",[self.ddLabel.text substringWithRange:result.range]];
NSRange phoneRange = result.range;
//这里需要判断是否是电话号码,并添加链接
if ([DDUtil isMobilePhoneOrtelePhone:actionString]) {
[self.ddLabel addLinkToPhoneNumber:actionString withRange:result.range];
}
}];
}
- 当然只判断这些肯定是不够的,像这种20899999999,很明显不是电话号,上面也匹配了。我们第二步就是筛选是手机号的并加上链接。这里我直接用了我们项目里的工具类,这个代码网上一搜一堆,不再介绍。
主要代码实现
* // 验证是固话或者手机号
*
* @param mobileNum 手机号
*
* @return 是否
*/
+ (BOOL)isMobilePhoneOrtelePhone:(NSString *)mobileNum {
if (mobileNum==nil || mobileNum.length ==0) {
return NO;
}
/**
* 手机号码
* 移动:134[0-8],135,136,137,138,139,150,151,157,158,159,182,187,188
* 联通:130,131,132,152,155,156,185,186
* 电信:133,1349,153,180,189
*/
NSString * MOBILE = @"^((13)|(14)|(15)|(17)|(18))\\d{9}$";// @"^1(3[0-9]|5[0-35-9]|8[025-9])\\d{8}$";
/**
10 * 中国移动:China Mobile
11 * 134[0-8],135,136,137,138,139,150,151,157,158,159,182,187,188
12 */
NSString * CM = @"^1(34[0-8]|(3[5-9]|5[017-9]|8[278])\\d)\\d{7}$";
/**
15 * 中国联通:China Unicom
16 * 130,131,132,152,155,156,185,186
17 */
NSString * CU = @"^1(3[0-2]|5[256]|8[56])\\d{8}$";
/**
20 * 中国电信:China Telecom
21 * 133,1349,153,180,189
22 */
NSString * CT = @"^1((33|53|8[09])[0-9]|349)\\d{7}$";
/**
25 * 大陆地区固话及小灵通
26 * 区号:010,020,021,022,023,024,025,027,028,029
27 * 号码:七位或八位
28 */
NSString * PHS = @"^((0\\d{2,3}-?)\\d{7,8}(-\\d{2,5})?)$";// @"^0(10|2[0-5789]-|\\d{3})\\d{7,8}$";
NSPredicate *regextestPHS = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", PHS];
NSPredicate *regextestmobile = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", MOBILE];
NSPredicate *regextestcm = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", CM];
NSPredicate *regextestcu = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", CU];
NSPredicate *regextestct = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", CT];
if (([regextestmobile evaluateWithObject:mobileNum] == YES)
|| ([regextestcm evaluateWithObject:mobileNum] == YES)
|| ([regextestct evaluateWithObject:mobileNum] == YES)
|| ([regextestcu evaluateWithObject:mobileNum] == YES)
|| ([regextestPHS evaluateWithObject:mobileNum]==YES)) {
return YES;
}
else{
return NO;
}
}
效果图
源代码
注意
没有做没加区号的号码匹配,其实我们项目里面只做手机号就行了。感兴趣的可以自己加。当然对这些特殊的110,120,也不会支持。这个在我们项目里根本是录不进去的,因为做了严格的输入限制,只能输11位手机号。作为展示,肯定不会有110,120,这种无聊的数据的。