NSPredicate 不能判断全角字符

1,423 阅读1分钟

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