NSPredicate 不能判斷全形字元

yang152412發表於2018-12-26

iOS 中的正規表示式判斷可以用兩種型別來實現,既 NSPredicateNSRegularExpression

一、 NSPredicate

NSPredicate 謂詞,結合 SELF MATCHES 來實現正規表示式的判斷。例如:

判斷是否是英文字母和數字

    NSString *text = @"AWEFDSF1234123";
    
    NSString *regexString = @"^[A-Za-z0-9]*$";
    NSPredicate *regex = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", regexString];
    BOOL result = [regex evaluateWithObject:text];

複製程式碼

但是專案上線一段時間後發現了 bug,複製貼上的字串有可能有全形字元,而這個NSPredicate驗證不出來。

例如:AWEFDSF1234123 也能驗證成功,而伺服器是不認 全形字元的,這就坑爹了。

二、使用NSRegularExpression

NSRegularExpressionCore Foundation中的正規表示式。功能也很多,可以返回把所有匹配結果的陣列,匹配的總數,第一個匹配結果,第一個匹配的range。

一般我們驗證的話只要是否匹配到就好了,可以用下面的方法:

    NSString *text = @"AWEFDSF1234123";
    NSString *regexString = @"^[A-Za-z0-9]*$";
    
    NSRegularExpression *regex = [[NSRegularExpression alloc] initWithPattern:regexString options:0 error:nil];
    NSTextCheckingResult *r = [regex firstMatchInString:text options:0 range:NSMakeRange(0, text.length)];
    BOOL result = r ? YES : NO;

複製程式碼

這個方法能正確返回結果。

再簡單封裝一下,使用更方便:

+ (BOOL)validateString:(NSString*)stringToSearch withRegex:(NSString*)regexString {
    
    if (![stringToSearch isKindOfClass:[NSString class]] ||
        ![regexString isKindOfClass:[NSString class]]) {
        return NO;
    }
    
    if (stringToSearch.length == 0 ||
        regexString.length == 0) {
        return NO;
    }
    
    NSRegularExpression *regex = [[NSRegularExpression alloc] initWithPattern:regexString options:0 error:nil];
    NSTextCheckingResult *r = [regex firstMatchInString:stringToSearch options:0 range:NSMakeRange(0, stringToSearch.length)];
    BOOL result = r ? YES : NO;
    return result;
}
複製程式碼

測試發現下面的方法判斷全形符號也能正確驗證:

NSRange range = [text rangeOfString:regexString options:NSRegularExpressionSearch];
    BOOL result = range.location == NSNotFound ? NO : YES;
    NSLog(@"Test isTaxNumber %@",@(result))
複製程式碼

三、關於匹配數字

用正規表示式匹配數字的時候,需要特別注意 \d匹配的不只是0-9這樣的阿拉伯數字,而是Unicode 裡面的 'Number, Decimal Digit集合,如果需要匹配0-9(大部分都是這樣吧),則需要寫成[0-9]。參考 這裡

四、全形和半形之間的轉換


#import <Foundation/Foundation.h>
 
@interface NSString (X)
 
/**
 全形轉半形
 @return 轉化後的文字
 */
- (NSString *)replaceSpecialWhitespace;
 
/**
 半形轉全形
 @return 轉化後的文字
 */
- (NSString *)replaceNormalWhiteSpace;
@end
 
#import "NSString+X.h"
 
@implementation NSString (X)
 
- (NSString *)replaceSpecialWhitespace{
    NSMutableString *convertedString = [self mutableCopy];
    CFStringTransform((CFMutableStringRef)convertedString, NULL, kCFStringTransformFullwidthHalfwidth, false);
    return [NSString stringWithString:convertedString];
}
- (NSString *)replaceNormalWhiteSpace{
    NSMutableString *convertedString = [self mutableCopy];
    CFStringTransform((CFMutableStringRef)convertedString, NULL, kCFStringTransformHiraganaKatakana, false);
    return [NSString stringWithString:convertedString];
}
@end
複製程式碼

參考資料

https://blog.csdn.net/j_r_k/article/details/78204578

https://www.jianshu.com/p/66ee05f4c7b0

全形半形轉換:

https://blog.csdn.net/j_r_k/article/details/78204578

https://www.cnblogs.com/Doule/p/6567418.html

全形英語字母,全形阿拉伯數字,漢語數字對應的unicode編碼:https://blog.csdn.net/mx472756841/article/details/53379762

相關文章