How to get all NSRange of a particular character in a NSString?
Asked Answered
M

4

20

I have two NSStrings: orgText and searchLetter.
I want to highlight every occurrences of the searchLetter in the orgText with a red color.
How can I get the NSRange of all occurrences of the searchLetter ?
for eg :

suppose: orgText = "abcahaiapaoiuiapplma"
         searchLetter = "a".

I want to hightlight all "a" occurrences in "abcahaiapaoiuiapplma" with red color.
Thanks.

Manual answered 16/12, 2011 at 11:44 Comment(0)
S
56

I wrote this method for my project - SUITextView with highlight:

- (NSMutableAttributedString*) setColor:(UIColor*)color word:(NSString*)word inText:(NSMutableAttributedString*)mutableAttributedString {

    NSUInteger count = 0, length = [mutableAttributedString length];
    NSRange range = NSMakeRange(0, length);

    while(range.location != NSNotFound)
    {
        range = [[mutableAttributedString string] rangeOfString:word options:0 range:range];
        if(range.location != NSNotFound) {
            [mutableAttributedString setTextColor:color range:NSMakeRange(range.location, [word length])];
            range = NSMakeRange(range.location + range.length, length - (range.location + range.length));
            count++; 
        }
    }

    return mutableAttributedString;
}

And in my category of NSMutableAttributedString:

- (void) setTextColor:(UIColor*)color range:(NSRange)range {
    // kCTForegroundColorAttributeName
    [self removeAttribute:(NSString*)kCTForegroundColorAttributeName range:range]; // Work around for Apple leak
    [self addAttribute:(NSString*)kCTForegroundColorAttributeName value:(id)color.CGColor range:range];
}
Sup answered 16/12, 2011 at 12:5 Comment(4)
I think there's an extra "}" floating around, but working great still in '14Aft
@Aft you are right. that method was written for multiple words :)Sup
What's the point of count? To see how many occurrences you've replaced while debugging?Periderm
For me (iOS 7) it only worked with other kinds of arguments in that category method. NSForegroundColorAttributeName instead of kCTForegroundColorAttributeName and a UIColor object instead of its CGColor property.Antistrophe
P
7

I'm not seeing any solution with regular expression, so I've created an elegant one, it may be useful for someone in the future.

- (BOOL)highlightString:(NSString *)string inText:(NSMutableAttributedString *)attributedString withColour:(UIColor *)color {
    NSError *_error;
    NSRegularExpression *_regexp = [NSRegularExpression regularExpressionWithPattern:string options:NSRegularExpressionCaseInsensitive error:&_error];
    if (_error == nil) {
        [_regexp enumerateMatchesInString:attributedString.string options:NSMatchingReportProgress range:NSMakeRange(0, attributedString.string.length) usingBlock:^(NSTextCheckingResult *result, NSMatchingFlags flags, BOOL *stop) {
            if (result.numberOfRanges > 0) {
                for (int i = 0; i < result.numberOfRanges; i++) {
                    [attributedString addAttribute:NSBackgroundColorAttributeName value:color range:[result rangeAtIndex:i]];
                }
            }
        }];
        return TRUE;
    } else {
        return FALSE;
    }
}
Palua answered 20/6, 2014 at 10:21 Comment(0)
S
2

Code crash at "setTextColor" for MutableAttributeString

instead of it use below code

NSDictionary *tempdict=[NSDictionary dictionaryWithObjectsAndKeys:[UIFont boldSystemFontOfSize:12.0],NSFontAttributeName,color,NSForegroundColorAttributeName, nil];
[mutableAttributedString setAttributes:tempdict range:NSMakeRange(range.location, [word length])];
Style answered 5/2, 2013 at 10:53 Comment(0)
L
-1

this is an easier way of doing it

NSString *str = @"hello world";
NSMutableAttributedString *attr = [[NSMutableAttributedString alloc] initWithString:str];
[attr addAttributes:@{NSForegroundColorAttributeName : [UIColor redColor]} 
              range:[str rangeOfString:@"world"]];
Lasley answered 1/9, 2015 at 10:54 Comment(1)
NOTE:this would only add attributes to the first substring occurrenceRaggletaggle

© 2022 - 2024 — McMap. All rights reserved.