lubilis lubilis - 24 days ago 9
iOS Question

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.

Answer

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;

}