iOS 開發中你不能不知道的一個 class

LaiYoung_發表於2016-11-23

你還在為不會寫正則而抓狂?

iOS 開發中你不能不知道的一個 class

你還在為如何識別字串中的電話號碼連結日期地址...並實現國際化而煩惱?
那麼你會在看完本文章之後不會抓狂,不會煩惱,依舊覺得生活很美好!
iOS 開發中你不能不知道的一個 class

進入正題!!!
其實 Apple 已經幫我們定義好了這麼一個 classNSDataDetector只是知道這個類的人甚少。 NSDataDetector它是繼承至NSRegularExpression的,也就是我們所說的正規表示式。NSDataDetector的使用很簡單,有一個類方法和一個例項方法。

+ (nullable NSDataDetector *)dataDetectorWithTypes:(NSTextCheckingTypes)checkingTypes error:(NSError **)error;
- (nullable instancetype)initWithTypes:(NSTextCheckingTypes)checkingTypes error:(NSError **)error NS_DESIGNATED_INITIALIZER;複製程式碼

這裡的type就是我們需要匹配的型別。這些 type 都是系統幫我們定義好的,當然我們也可以自己自定義type

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 NS_ENUM_AVAILABLE(10_7, 4_0)  = 1ULL << 10,           // regular expression matches
    NSTextCheckingTypePhoneNumber NS_ENUM_AVAILABLE(10_7, 4_0)        = 1ULL << 11,           // phone number detection
    NSTextCheckingTypeTransitInformation NS_ENUM_AVAILABLE(10_7, 4_0) = 1ULL << 12            // transit (e.g. flight) info detection
};複製程式碼

這僅僅是第一步,這一步就好比我們寫好了正規表示式,那麼下一步就是將它運用在字串中進行匹配。這裡有5種方法可共選擇

//1.檢測然後對每個檢測到的資料進行操作
- (void)enumerateMatchesInString:(NSString *)string options:(NSMatchingOptions)options range:(NSRange)range usingBlock:(void (^)(NSTextCheckingResult *result, NSMatchingFlags flags, BOOL *stop))block;

//2.檢測獲得檢測得到的陣列
- (NSArray *)matchesInString:(NSString *)string options:(NSMatchingOptions)options range:(NSRange)range;

//3.獲得檢測得到的總數
- (NSUInteger)numberOfMatchesInString:(NSString *)string options:(NSMatchingOptions)options range:(NSRange)range;

//4.第一個檢測到的資料
- (NSTextCheckingResult *)firstMatchInString:(NSString *)string options:(NSMatchingOptions)options range:(NSRange)range;

//5.第一檢測到的資料的Range
- (NSRange)rangeOfFirstMatchInString:(NSString *)string options:(NSMatchingOptions)options range:(NSRange)range;複製程式碼

匹配到了對應的字串並知道了字串對應所在的NSRange,接下來就可以利用NSMutableAttributedString來讓這些字串高亮。

高亮文字的事件響應

UITextView

  1. UITextView中可以直接響應高亮文字的事件,先設定 UITextView 的delegate,並實現- (BOOL)textView:(UITextView *)textView shouldInteractWithURL:(NSURL *)URL inRange:(NSRange)characterRange協議。此時要設定 UITextView 的editableNO,不然不會走回撥的API
  2. 做完這些之後還需要設定文字響應的 range,根據上面獲取到的文字和 range,我們可以根據屬性字串的- (void)addAttribute:(NSString *)name value:(id)value range:(NSRange)range;方法設定響應事件,nameNSLinkAttributeNamevalue為響應事件接收到的 value,range為需要響應事件的 range。

UILabel

其實在 Label 中實現文字高亮並實現事件的響應,在 Github 上面有很多庫了,例如YYText中的 YYLabel、TTTAttributedLabel等等,太多了就不一一列舉了,但是在YYLabel中同時實現長按事件和點選事件的時候,響應長按事件之後還會響應點選事件,這時候就需要我們自己手動處理一下了。

參考文章:初識 NSDataDetector

相關文章