最近項目中碰到了這樣一個需求,需要在一段文字中識別出手機號,并加上特殊顏色,和點擊事件。下面說下我的思路,拋磚引玉。(如果你有更好的想法,不妨交流下)
前提是基于TTTAttributedLabel實現的。因為TTTAttributedLabel已經做了添加鏈接,我們目的是找出應該在哪里加鏈接,關于怎么加上,以及點擊鏈接的代理事件不是本文重點。工欲善其事,必先利其器嗎。(以下內容僅以國內固話和手機號為例,不涉及國外電話)
思路
主要分為兩步,
-
先粗略找出字符串中可能為固話和手機號的子字符串及其在該字符串中的位置range。
什么是可能為電話號碼的字符串,比如18000000000(連續11位數字),010-66666666(3位區號-8位號碼)還有(3-7,4-8,4-7)以及區號和號碼之間不用“-”的,這些都是有可能為電話號碼的。
用正則表達式表示就是#define PHONEREGULAR @"\\d{3,4}[- ]?\\d{7,8}"http://匹配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;
}
}
效果圖
1.png
源代碼
注意
沒有做沒加區號的號碼匹配,其實我們項目里面只做手機號就行了。感興趣的可以自己加。當然對這些特殊的110,120,也不會支持。這個在我們項目里根本是錄不進去的,因為做了嚴格的輸入限制,只能輸11位手機號。作為展示,肯定不會有110,120,這種無聊的數據的。