Search code examples
iosobjective-cnsstringnstextattachment

Replace occurrences of NSString with NSTextAttachment


I have a UITextView and I want to replace some strings with specific images using NSTextAttachment. I'm able to insert an image attachment to the UITextView and I have a method that, from the text view's attributed text, returns a NSString replacing attachments with specific NSString:

-(NSString*)getStringFromAttributedString{ 
__block NSString *str = self.attributedText.string; // Trivial String representation
__block NSMutableString *string = [NSMutableString new]; // To store customized text

[self.attributedText enumerateAttributesInRange:NSMakeRange(0, self.attributedText.length) options:0 usingBlock:^(NSDictionary *attributes, NSRange range, BOOL *stop){     
    // enumerate through the attributes
    NSString *v;   
    NSObject *x = [attributes valueForKey:@"NSAttachment"];  
    if(x){ // YES= This is an attachment       
        v = [Fuctions getObjectTag:x];     
        if(v == nil){
            v=@"";
        }
    }else{
        v = [str substringWithRange:range]; // NO=This is a text block.
    }  
    // append value to string
    [string appendString:v];
}];
return string;
}

Now I need a method that returns a NSAttributedString from NSString, replacing some occurrences of string with image attachment, something like this but I'm not able to make it work.

-(NSMutableAttributedString*)getAttributedStringFromString:(NSString*)string{

    // create NSMutableAttributedString from NSString in input
    NSMutableAttributedString *attrString = [[NSMutableAttributedString alloc] initWithString:string]; 
    // create the attachment with image
    NSTextAttachment *textAttachment = [[NSTextAttachment alloc] init];
    textAttachment.image = [UIImage imageNamed:@"myImageName.png"];
    textAttachment.bounds = (CGRect) {0, -2, textAttachment.image.size};
    // create NSMutableAttributedString with image attachment
    NSMutableAttributedString *attrStringWithImage = [[NSAttributedString attributedStringWithAttachment:textAttachment] mutableCopy];

    // here I'd like to replace all occurrences of a string (":D" this string for example) with my NSMutableAttributedString with image attachment).

    return string;
}

How can I do?

Thanks, hope i explained myself.


Solution

  • This is my working solution:

    -(NSMutableAttributedString*)getEmoticonStringFromString:(NSString*)string{
    
    NSMutableAttributedString *final = [NSMutableAttributedString new]; //To store customized text
    NSInteger len = [string length];
    unichar buffer[len];
    [string getCharacters:buffer range:NSMakeRange(0, len)];
    
    for(int i = 1; i < len; i++) {
        if(buffer[i-1] == ':' && buffer[i] == 'D'){
    
            NSMutableAttributedString *attrString = [[NSMutableAttributedString alloc] initWithString:string];
    
            NSTextAttachment *textAttachment = [[NSTextAttachment alloc] init];
            textAttachment.image = [Functions scaleImage:[UIImage imageNamed:@"myImageName"] toSize:CGSizeMake(18.0f, 18.0f)];
            textAttachment.bounds = (CGRect) {0, -2, textAttachment.image.size};
    
            NSMutableAttributedString *attrStringWithImage = [[NSAttributedString attributedStringWithAttachment:textAttachment] mutableCopy];
    
            NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init] ;
            [paragraphStyle setAlignment:NSTextAlignmentLeft];
            [paragraphStyle setLineSpacing:2.0f];
            [attrString addAttribute:NSParagraphStyleAttributeName value:paragraphStyle range:NSMakeRange(0, [attrString length])];
    
            [final insertAttributedString:attrStringWithImage atIndex:final.length];
    
            i++;
        }else{
    
            [final insertAttributedString:[[NSAttributedString alloc] initWithString:[NSString stringWithFormat:@"%c", buffer[i-1]]] atIndex:final.length];
            if(i == len-1){
    
                [final insertAttributedString:[[NSAttributedString alloc] initWithString:[NSString stringWithFormat:@"%c", buffer[i]]] atIndex:final.length];
            }
        }
    }
    return final;
    

    }