現在APP開發對效果要求越來與豐富,各種特效層出不窮。其中以動畫效果和文字以富文本展示居多。
在網上也看了好幾種方法,感覺有的處理的麻煩了,下面是我總結的獲取子字符串所有Rang的一些方法:
字符串做富文本處理需要通過NSMutableAttributedString來處理,先創建一個NSMutableAttributedString對象:
NSMutableAttributedString *attribtStr = [[NSMutableAttributedString alloc] initWithString:@"父字符串"];
1、使用NSRegularExpression來處理
//初始化NSRegularExpression
NSRegularExpression *regularExpression = [NSRegularExpression regularExpressionWithPattern:@"你的正則表達式" options:0 error:nil]; //遍歷字符串,usingBlock中返回子字符串的狀態,在usingBlock中處理子字符串
[regularExpression enumerateMatchesInString:attribtStr.string options:0 range:NSMakeRange(0, attribtStr.string.length) usingBlock:^(NSTextCheckingResult * _Nullable result, NSMatchingFlags flags, BOOL * _Nonnull stop) { //給子字符串添加雙刪除線 [attribtStr addAttribute:NSStrikethroughStyleAttributeName value:[NSNumber numberWithInteger:NSUnderlineStyleDouble] range:result.range]; //刪除線設置為紅色 [attribtStr addAttribute:NSStrikethroughColorAttributeName value:[UIColor redColor] range:result.range]; }];
上面方法是直接在遍歷中處理匹配的子字符串,下面的是先得到所有子字符串的狀態集,再做對應處理:
NSArray *regularExpressionArr = [regularExpression matchesInString:attribtStr.string options:0 range:NSMakeRange(0, attribtStr.string.length)];
得到子字符串的數組集合,需要做什么處理,通過循環判斷就可以完成了。
for (NSTextCheckingResult *result in regularExpressionArr) { NSRange rang = [result range]; NSLog(@"%lu",rang.location); [attribtStr addAttribute:NSStrikethroughStyleAttributeName value:[NSNumber numberWithInteger:NSUnderlineStyleDouble] range:result.range]; [attribtStr addAttribute:NSStrikethroughColorAttributeName value:[UIColor redColor] range:result.range]; }
NSRegularExpression的下面幾個方法在其他情況下也是很好用的:
//獲取子字符串數目
- (NSUInteger)numberOfMatchesInString:(NSString *)string options:(NSMatchingOptions)options range:(NSRange)range; //獲取第一個子字符串的NSTextCheckingResult
- (nullable NSTextCheckingResult *)firstMatchInString:(NSString *)string options:(NSMatchingOptions)options range:(NSRange)range; //獲取指定rang內第一個符合要求的子字符串
- (NSRange)rangeOfFirstMatchInString:(NSString *)string options:(NSMatchingOptions)options range:(NSRange)range;
2.通過遞歸獲得所有子字符串的rang數組(遞歸的優缺點就不在扯了,慎用)
//通過遞歸獲取所有子字符串location - (void)rangeOfString:(NSString*)searchString fatherString:(NSString*)fatherStr options:(NSStringCompareOptions)mask range:(NSRange)rangeOfReceiverToSearch { //獲取指定范圍內第一個匹配的子字符串rang,和上面NSRegularExpression的一個方法效果一樣
NSRange rang = [fatherStr rangeOfString:searchString options:mask range:rangeOfReceiverToSearch];
//判斷搜尋范圍來決定是否完成搜尋 if (rang.location >fatherStr.length - searchString.length) { return; }
//NSRang不能存儲在數組中,所以這里存的是rang的location [strLocationRangArr addObject:[NSNumber numberWithInteger:rang.location]];
//遞歸搜尋 [self rangeOfString:searchString fatherString:fatherStr options:mask range:NSMakeRange(rang.location+searchString.length, fatherStr.length-rang.location-searchString.length)]; }
調用示例:
strLocationRangArr = [NSMutableArray array]; [self rangeOfString:@"CoreText" fatherString:attribtStr.string options:0 range:NSMakeRange(0, attribtStr.string.length)]; for (NSNumber *location in strLocationRangArr) { [attribtStr addAttribute:NSStrikethroughStyleAttributeName value:[NSNumber numberWithInteger:NSUnderlineStyleDouble] range:NSMakeRange([location integerValue], 8)]; [attribtStr addAttribute:NSStrikethroughColorAttributeName value:[UIColor redColor] range:NSMakeRange([location integerValue], 8)]; }
3.通過字符串- (NSArray<NSString *> *)componentsSeparatedByString:(NSString *)separator;方法獲得的切割數組處理獲得子字符串rang集合。
NSArray *arr = [attribtStr.string componentsSeparatedByString:@"searchString"];
通過數組的子字符串去匹配attribtStr.string獲取searchString的location,
這種方法需要處理的地方比較多,首先要考慮arr中第一個、最后一個和連續的是否是@“”,在着就是數組中不可避免會出現相同切割為相同的子串。
例如:@“123654789123654789”這樣要search@“654”就會出現兩個@“123”和@“789”,在判斷的時候要在此處處理重復問題,小的表示有了上面兩種方法就沒有在對這種想法再做深入的實現。
相對NSRegularExpression的簡單快速的,其他方法用來作為思路還是不錯的。