1

I'm having an issue finding multiple groups of substrings indicated by a pair of ** characters, and bolding them. for example in this NSString:

The Fox has **ran** around the **corner**

should read: The fox has ran around the corner

here is my code:

NSString *questionString = queryString;
NSMutableAttributedString *mutableAttributedString = [[NSMutableAttributedString alloc] initWithString:questionString];

NSRange range = [questionString rangeOfString:@"\\*{2}([^*]+)\\*{2}" options:NSRegularExpressionSearch];
if (range.location != NSNotFound) {
    [mutableAttributedString setAttributes:@{NSFontAttributeName:[UIFont boldSystemFontOfSize:size]} range:range];
}

[[mutableAttributedString mutableString] replaceOccurrencesOfString:@"**" withString:@"" options:NSCaseInsensitiveSearch range:NSMakeRange(0, queryString.length)];

return mutableAttributedString;

this code only catches one pair of indicated characters, so all i get back is :The fox has ran around the corner

any ideas?

3254523
  • 3,016
  • 7
  • 29
  • 43
  • @rmaddy nah, not a dupe. i've asked a different question in there. i actually got an answer there and applied it to new code. this question is a different question – 3254523 Jan 14 '14 at 21:14
  • Have you tired to run the regex replace in a global context? –  Jan 14 '14 at 21:14
  • How is it not the same? Both ask how to convert a delimited value to an attributed string. – rmaddy Jan 14 '14 at 21:31

1 Answers1

1

You have to enumerate all matches of the regular expression. It is a bit tricky because all ranges shift when you remove the limiting "**" pairs.

This seems to do the job:

NSString *questionString = @"The Fox has **ran** around the **corner**";
NSMutableAttributedString *mutableAttributedString = [[NSMutableAttributedString alloc] initWithString:questionString];

NSError *error = nil;
NSString *pattern = @"(\\*{2})([^*]+)(\\*{2})";
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:pattern options:0 error:&error];

__block NSUInteger shift = 0; // number of characters removed so far
[regex enumerateMatchesInString:questionString options:0 range:NSMakeRange(0, [questionString length])
     usingBlock:^(NSTextCheckingResult *result, NSMatchingFlags flags, BOOL *stop) {
         NSRange r1 = [result rangeAtIndex:1]; // location of first **
         NSRange r2 = [result rangeAtIndex:2]; // location of word in between
         NSRange r3 = [result rangeAtIndex:3]; // location of second **
         // Adjust locations according to the string modifications:
         r1.location -= shift;
         r2.location -= shift;
         r3.location -= shift;
         // Set attribute for the word:
         [mutableAttributedString setAttributes:@{NSFontAttributeName:[UIFont boldSystemFontOfSize:12.0]} range:r2];
         // Remove the **'s:
         [[mutableAttributedString mutableString] deleteCharactersInRange:r3];
         [[mutableAttributedString mutableString] deleteCharactersInRange:r1];
         // Update offset:
         shift += r1.length + r3.length;
     }];

Result (in debugger console):

The Fox has {
}ran{
    NSFont = "<UICTFont: 0xc03efb0> font-family: \".HelveticaNeueInterface-MediumP4\"; font-weight: bold; font-style: normal; font-size: 12.00pt";
} around the {
}corner{
    NSFont = "<UICTFont: 0xc03efb0> font-family: \".HelveticaNeueInterface-MediumP4\"; font-weight: bold; font-style: normal; font-size: 12.00pt";
}
Martin R
  • 529,903
  • 94
  • 1,240
  • 1,382