Search code examples
iosobjective-cregexnsstringnsmutableattributedstring

NSString find regular expression and replace it with image (NSMutableAttributeString)


I know that something like this has already been asked but I found no solution for my issue.

So, I have a NSString, which sometimes includes in the text a image name, like:

Lorem ipsum....
image.png
... dolor sit elit lamet

I'd like to put in that space an image named 'image.png' in my NSMutableAttributedString.

This is my code to fetch matchings

NSString *regEx = @"([a-z])+(?:([0-9])+){0,1}.png";
NSError *error = nil;
NSRegularExpression *regex = [NSRegularExpression
                              regularExpressionWithPattern:regEx
                              options:NSRegularExpressionCaseInsensitive error:&error];
if(error != nil){
    NSLog(@"Error: %@",error);
} else{
    [regex enumerateMatchesInString:myString options:0 range:NSMakeRange(0, [myString length]) usingBlock:^(NSTextCheckingResult *match, NSMatchingFlags flags, BOOL *stop){
        // your code to handle matches here

        NSLog(@"found!");
    }];
}

How can I add an image in a NSMutableAttributedString, calling imageNamed function for each found sub-string?


Solution

  • Apparently I resolved it. Inside the for there is the code to replace a substring with an image in the NSMutableAttributedString. Also I decided to put a reversed for in inspiration to a previous answer in a question similar (but different) like this

    NSMutableAttributedString *formattedText = myString.mutableAttributedString;
    
    // Look for image
    NSString *regEx = @"([a-z])+(?:([0-9])+){0,1}.png";
    NSError *error = nil;
    NSRegularExpression *regex = [NSRegularExpression
                                  regularExpressionWithPattern:regEx
                                  options:NSRegularExpressionCaseInsensitive error:&error];
    if(error != nil){
        NSLog(@"Error: %@",error);
    } else{
        NSArray *matches = [regex matchesInString:myString
                                          options:kNilOptions
                                            range:NSMakeRange(0, myString.length)];
        for (NSTextCheckingResult *result in [matches reverseObjectEnumerator])
        {
            NSString *insideString = [myString substringWithRange:[result rangeAtIndex:0]];
            UIImage *image = [UIImage imageNamed:insideString];
            NSTextAttachment *imageAttachment = [NSTextAttachment new];
            imageAttachment.image = image;
            NSAttributedString *replacementForTemplate = [NSAttributedString attributedStringWithAttachment:imageAttachment];
            [formattedText replaceCharactersInRange:result.range
                               withAttributedString:replacementForTemplate];
    
            NSLog(@"found! -> %@", insideString);
    
        }
    }
    

    Instead the mutableAttributedString property belongs to a NSString Category. This is the code of it

    - (NSMutableAttributedString *)mutableAttributedString {
        return [[NSMutableAttributedString alloc] initWithString:self];
    }