1

I have an task where I need to count the occurrences of errors in a log file and I know how to do that. Now Im trying to change the font color of these occurrences. I have it kinda working but it doesn't change the whole word to the wanted color and for the next occurrence of that string it shifts over 3 characters. See image below.

enter image description here

I searched for the word "Checked" and it gave me these results.

Below is the code that I am using

NSArray * lines = [words componentsSeparatedByCharactersInSet:[NSCharacterSet newlineCharacterSet]];
    wordresult = [lines componentsJoinedByString:@""];





if (occS2 == 1)
    {
        NSString * box2 = [_occSearchTwoTextBox stringValue];
        NSUInteger countFatal = 0, length4 = [wordresult length];
        NSRange range4 = NSMakeRange(0, length4);
        while(range4.location != NSNotFound)
        {
            range4 = [wordresult rangeOfString: box2 options:NSCaseInsensitiveSearch range:range4];

            [self.stringLogTextView setTextColor:[NSColor redColor] range:range4];
            NSLog(@"Occurance Edited");

            if(range4.location != NSNotFound)
            {
                range4 = NSMakeRange(range4.location + range4.length, length4 - (range4.location + range4.length));
                countFatal++;
            }
        }
        NSString * FatalCount = [NSString stringWithFormat:@"%lu", (unsigned long)countFatal];
        [_customSearchTwoTextBox setStringValue:FatalCount];
    }

Can anyone please point me to where to why its shifting? I can only assume that it has something to do with my range but I'm not sure what to do to resolve.

Thanks for everyones time!

Breathable
  • 89
  • 10

1 Answers1

0

I'm not sure why your method isn't working correctly, but I would do it a different way. Using enumerateSubstringsInRange:options:usingBlock:, you can enumerate your string by word, and get the range of each word passed in to the method for you. If the word is "Checked", you can increment your count and also set the attributes for that range of a mutable attributed string. Here is an example of how to use that method,

    NSString *theText = @"] Tables initialized\n]Database version Checked\n]Got login id-1\n] Tables initialized\n]Database version Checked\n]Got login id-1\n] Tables initialized\n]Database version Checked\n]Got login id-1\n";
    NSMutableAttributedString *attrib = [[NSMutableAttributedString alloc] initWithString:theText];
    NSDictionary *dict = @{NSForegroundColorAttributeName:[NSColor greenColor]};

    __block int count = 0;
    [theText enumerateSubstringsInRange:NSMakeRange(0, theText.length) options:NSStringEnumerationByWords usingBlock:^(NSString *substring, NSRange substringRange, NSRange enclosingRange, BOOL *stop) {
        if ([substring isEqualToString:@"Checked"]) {
            [attrib setAttributes:dict range:substringRange];
            count ++;
        };
    }];

    self.textView.textStorage.attributedString = attrib;
    NSLog(@"count is: %d",count);

enter image description here

rdelmar
  • 103,982
  • 12
  • 207
  • 218
  • Your example works great by itself but when I connect it to my textview it doesn't work as designed. It takes out of the line breaks in the textview even when I change setAttributes to addAttributes and it doesn't change the text color and also it says the count is 0. – Breathable Oct 31 '14 at 13:08
  • What is the string in your text view? Is it an NSString or an attributed string? How are you passing in the text view's string to the enumeration method? – rdelmar Oct 31 '14 at 14:49
  • As I back tracked where I populate the view I found my error I was pulling the wrong string. My apologies my bad. Its working great now. Thanks for all your help @rdelmar – Breathable Oct 31 '14 at 16:31
  • Heres an additional question , I have multiple searches to do in a single log file. With this method I will search for the first one then the second one but the second overrides the first attributes and only shows the the second searched text. Not sure it this should be an additional question but how would get both searches to show. For example how would I get "Checked" and "version" to show green from 2 methods? – Breathable Oct 31 '14 at 18:35
  • I actually figured that out sorry again my own mistakes. – Breathable Oct 31 '14 at 19:24
  • as I move forward with the finding the occurrences in log files Im finding that from the example above Im looking for "Checked" the code will find it but IF I look for "version Checked" it doesn't find it but looking for individual words "version" or "Checked" it works. One error I'm looking for is "Could not connect to Postgres" how would I look for substrings with multiple words with spaces ? – Breathable Nov 06 '14 at 15:03
  • Another example is "123Checked" is not found when looking for "Checked" – Breathable Nov 06 '14 at 15:04
  • @Breathable, these new conditions you're putting on the search change the nature of the problem considerably. The "123Checked" case can be handled fairly easily, by checking for substring hasPrefix: (and hasSuffix if you want that possibility also) in addition to isEqualToString. Checking for multiple words will be harder. You would need to keep track of the previous substring, and when you find "Checked", look at that previous substring, and see if it matches "version". Depending on how many other odd cases there are, you might need to go to a completely different approach. – rdelmar Nov 06 '14 at 16:01
  • Ok sounds good I will play with it. Thanks so much for your help! – Breathable Nov 06 '14 at 16:10