神奇的字符串翻譯NSDataDetector

前言

我們經(jīng)常需要對(duì)一個(gè)字符串內(nèi)容的類型進(jìn)行判斷,是否是地址,電話或者URL.如果手動(dòng)去處理,經(jīng)常容易忽略一些判斷規(guī)則的細(xì)節(jié),導(dǎo)致結(jié)果不準(zhǔn)確.

系統(tǒng)給我們提供了一個(gè)類NSDataDetector,它可以用于判斷字符串內(nèi)部?jī)?nèi)容的類型,而且,一段字符串中如果同時(shí)含有電話,地址,URL等,也可以區(qū)分出來,真是神奇的字符串翻譯,下面我們就對(duì)這個(gè)magic class進(jìn)行詳細(xì)介紹.

NSDataDetector

NSDataDetectorNSRegularExpression的子類.看一下官方文檔的介紹

A specialized regular expression object that matches natural language text for predefined data patterns

NSDataDetector是用于匹配自然語言字符串來確定對(duì)象類型的特殊的正則表達(dá)式對(duì)象.

NSDataDetector用法

目前NSDataDetector類可以用于匹配的類型有:日期, 地址, 鏈接, 手機(jī)號(hào), 物流信息.匹配結(jié)果通過返回 NSTextCheckingResult 對(duì)象來表述.

NSTextCheckingResult

NSTextCheckingResult是表示匹配結(jié)果的類,需要注意的是NSTextCheckingResult可以用來表示NSRegularExpressionNSDataDetector的結(jié)果,但是通過NSDataDetector匹配返回的NSTextCheckingResult和父類NSRegularExpression返回的是不同的.

必要屬性,存在于所有的解析結(jié)果中.

@property (readonly) NSTextCheckingType resultType;
@property (readonly) NSRange range;

可選屬性,只有在匹配到特定類型時(shí),某些屬性才會(huì)有值.

@property (nullable, readonly, copy) NSOrthography *orthography;
@property (nullable, readonly, copy) NSArray<NSDictionary<NSString *, id> *> *grammarDetails;
@property (nullable, readonly, copy) NSDate *date;
@property (nullable, readonly, copy) NSTimeZone *timeZone;
@property (readonly) NSTimeInterval duration;
@property (nullable, readonly, copy) NSDictionary<NSTextCheckingKey, NSString *> *components API_AVAILABLE(macos(10.7), ios(4.0), watchos(2.0), tvos(9.0));
@property (nullable, readonly, copy) NSURL *URL;
@property (nullable, readonly, copy) NSString *replacementString;
@property (nullable, readonly, copy) NSArray<NSString *> *alternativeStrings API_AVAILABLE(macos(10.9), ios(7.0), watchos(2.0), tvos(9.0));
@property (nullable, readonly, copy) NSRegularExpression *regularExpression API_AVAILABLE(macos(10.7), ios(4.0), watchos(2.0), tvos(9.0));
@property (nullable, readonly, copy) NSString *phoneNumber API_AVAILABLE(macos(10.7), ios(4.0), watchos(2.0), tvos(9.0));

提到了匹配的類型,我們來看一下NSTextCheckingType resultType都包含哪些類型.

typedef NS_OPTIONS(uint64_t, NSTextCheckingType) {    // a single type
    NSTextCheckingTypeOrthography           = 1ULL << 0,            // language identification
    NSTextCheckingTypeSpelling              = 1ULL << 1,            // spell checking
    NSTextCheckingTypeGrammar               = 1ULL << 2,            // grammar checking
    NSTextCheckingTypeDate                  = 1ULL << 3,            // date/time detection
    NSTextCheckingTypeAddress               = 1ULL << 4,            // address detection
    NSTextCheckingTypeLink                  = 1ULL << 5,            // link detection
    NSTextCheckingTypeQuote                 = 1ULL << 6,            // smart quotes
    NSTextCheckingTypeDash                  = 1ULL << 7,            // smart dashes
    NSTextCheckingTypeReplacement           = 1ULL << 8,            // fixed replacements, such as copyright symbol for (c)
    NSTextCheckingTypeCorrection            = 1ULL << 9,            // autocorrection
    NSTextCheckingTypeRegularExpression API_AVAILABLE(macos(10.7), ios(4.0), watchos(2.0), tvos(9.0))  = 1ULL << 10,           // regular expression matches
    NSTextCheckingTypePhoneNumber API_AVAILABLE(macos(10.7), ios(4.0), watchos(2.0), tvos(9.0))        = 1ULL << 11,           // phone number detection
    NSTextCheckingTypeTransitInformation API_AVAILABLE(macos(10.7), ios(4.0), watchos(2.0), tvos(9.0)) = 1ULL << 12            // transit (e.g. flight) info detection
};

NSDataDetector能匹配的類型日期, 地址, 鏈接, 手機(jī)號(hào), 物流信息.只有

NSTextCheckingTypeDate
NSTextCheckingTypeAddress
NSTextCheckingTypeLink
NSTextCheckingTypePhoneNumber
NSTextCheckingTypeTransitInformation

NSDataDetector返回的結(jié)果肯定屬于dataDetectorTypes類型的某一種,并且根據(jù)結(jié)果類型的不同,匹配對(duì)應(yīng)的屬性.比如
日期類型NSTextCheckingTypeDate會(huì)包含NSDateNSTimeZone類型的timeZoneduration.
鏈接類型NSTextCheckingTypeLink會(huì)包含NSURL等.

示例

以下代碼通過NSDataDetector來判斷手機(jī)號(hào)URL,如果失敗會(huì)返回error.

NSError *error = nil; 
NSDataDetector *detector = [NSDataDetector dataDetectorWithTypes: NSTextCheckingTypeLink | NSTextCheckingTypePhoneNumber error:&error];

NSDataDetector實(shí)例創(chuàng)建后,可以通過NSRegularExpression的方法numberOfMatches(in:options:range:)來獲得字符串在某個(gè)rang內(nèi)匹配的個(gè)數(shù).

NSUInteger numberOfMatches = [detector numberOfMatchesInString:string options:0 range:NSMakeRange(0, [string length])];

如果只是想獲取整個(gè)字符串的第一個(gè)匹配對(duì)象,numberOfMatches(in:options:range:)方法就可以.但是類型判斷不同于正則表達(dá)式的地方在于,客戶端會(huì)更注重分析后的附加信息.也就是NSTextCheckingResult對(duì)應(yīng)的可選屬性.

result的附加信息取決于其所屬的類型.如果是NSTextCheckingTypeLink類型,那么屬性URL就是關(guān)鍵的附加信息.如果是NSTextCheckingTypePhoneNumber類型,則phoneNumber是附加信息.

NSDateDetector的兩個(gè)方法 matches(in:options:range:)firstMatch(in:options:range:)都可以用于獲取解析結(jié)果.不同的是matches(in:options:range:)會(huì)返回所有的匹配結(jié)果,而firstMatch(in:options:range:)只會(huì)返回第一個(gè)匹配結(jié)果.

下面的代碼段就是獲取字符串中所有的鏈接電話號(hào)碼的匹配結(jié)果.

NSArray *matches = [detector matchesInString:string options:0 range:NSMakeRange(0, [string length])]; 
for (NSTextCheckingResult *match in matches) {
     NSRange matchRange = [match range]; 
     if ([match resultType] == NSTextCheckingTypeLink) { 
        NSURL *url = [match URL]; 
     } else if ([match resultType] == NSTextCheckingTypePhoneNumber) { 
        NSString *phoneNumber = [match phoneNumber];
   } 
}

NSRegularExpression類的enumerator方法是匹配中最常用的方法.該方法運(yùn)行我們多次去匹配一個(gè)字符串,在回調(diào)中自由地實(shí)現(xiàn)各種定制化需求,并且可以隨時(shí)控制遍歷停止的時(shí)機(jī).通過block回調(diào)的屬性BOOL *stop可以停止遍歷.

下面是一個(gè)在匹配了特定次數(shù)后停止遍歷的一個(gè)示例,可以用作參考.

__block NSUInteger count = 0;
 [detector enumerateMatchesInString:string 
                                options:0 
                                range:NSMakeRange(0, [string length])    
                                usingBlock:^(NSTextCheckingResult *match, NSMatchingFlags flags, BOOL *stop) { 
       NSRange matchRange = [match range];
       if ([match resultType] == NSTextCheckingTypeLink) { 
            NSURL *url = [match URL];
        } else if ([match resultType] == NSTextCheckingTypePhoneNumber) {
            NSString *phoneNumber = [match phoneNumber]; 
        }
         if (++count >= 100) *stop = YES;
 }];

注意

NSDataDetector只適用于解析特定類型的自然語言.只使用一定的情況匹配,并不是全能的.

如果文本具有特殊的格式,一個(gè)使用對(duì)應(yīng)的系統(tǒng)提供的類型轉(zhuǎn)換formatter來處理.比如想解析時(shí)間戳類型的數(shù)據(jù),就應(yīng)該使用DateFormatter類來解析,并輸出NSDate對(duì)象.

如果文本是特定的類型如XMLJSON,那么應(yīng)該先摘取自然語言,使用
XMLParserJSONSerialization進(jìn)行解析.

相關(guān)文檔

NSHipster的NSDataDetector

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容