iOS 7 TextKit – ¿Cómo insertar imágenes en línea con el texto?

Estoy tratando de obtener el siguiente efecto utilizando una UITextView:

enter image description here

Básicamente quiero insertar una imagen entre texto. La imagen simplemente puede ocupar 1 fila de espacio, por lo que no es necesario envolver.

Intenté simplemente agregar una UIView a la subvista:

UIView *pictureView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 25, 25)]; [pictureView setBackgroundColor:[UIColor redColor]]; [self.textView addSubview:pictureView]; 

Pero parece flotar sobre el texto y cubrirlo.

Leí un poco sobre las rutas de exclusión que parece ser una forma de implementar esto. Sin embargo, no quiero posicionar la imagen de forma absoluta, sino que debe fluir con el texto (similar a cómo comporta en HTML).

    Deberá usar una cadena atribuida y agregar la imagen como instancia de NSTextAttachment :

     NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithString:@"like after"]; NSTextAttachment *textAttachment = [[NSTextAttachment alloc] init]; textAttachment.image = [UIImage imageNamed:@"whatever.png"]; NSAttributedString *attrStringWithImage = [NSAttributedString attributedStringWithAttachment:textAttachment]; [attributedString replaceCharactersInRange:NSMakeRange(4, 1) withAttributedString:attrStringWithImage]; 

    Podría intentar usar NSAttributedString y NSTextAttachment. Eche un vistazo al siguiente enlace para obtener más detalles sobre cómo personalizar NSTextAttachment para cambiar el tamaño de la imagen. http://ossh.com.au/design-and-technology/software-development/implementing-rich-text-with-images-on-os-x-and-ios/

    En mi ejemplo, cambio el tamaño de la imagen para que se ajuste al ancho, en su caso es posible que desee cambiar el tamaño de la imagen para que coincida con la altura de la línea.

    Código de @ bilobatum convertido a Swift para los necesitados:

     var attributedString = NSMutableAttributedString(string: "like after") var textAttachment = NSTextAttachment() textAttachment.image = UIImage(named: "whatever.png") var attrStringWithImage = NSAttributedString.attributedStringWithAttachment(textAttachment) attributedString.replaceCharactersInRange(NSMakeRange(4, 1), withAttributedString: attrStringWithImage) 

    Ampliando la respuesta de @ bilobatum y usando esta categoría desde otra pregunta. Yo cociné esto:

    Uso:

     UILabel *labelWithImage = [UILabel new]; labelWithImage.text = @"Tap [new-button] to make a new thing!"; NSAttributedString *stringWithImage = [labelWithImage.attributedText attributedStringByReplacingOccurancesOfString:@"[new-button]" withImage:[UIImage imageNamed:@"MyNewThingButtonImage"] scale:0]; labelWithImage.attributedText = stringWithImage; 

    Implementación:

     @interface NSMutableAttributedString (InlineImage) - (void)replaceCharactersInRange:(NSRange)range withInlineImage:(UIImage *)inlineImage scale:(CGFloat)inlineImageScale; @end @interface NSAttributedString (InlineImages) - (NSAttributedString *)attributedStringByReplacingOccurancesOfString:(NSString *)string withInlineImage:(UIImage *)inlineImage scale:(CGFloat)inlineImageScale; @end 

    .

     @implementation NSMutableAttributedString (InlineImages) - (void)replaceCharactersInRange:(NSRange)range withInlineImage:(UIImage *)inlineImage scale:(CGFloat)inlineImageScale { if (floorf(inlineImageScale) == 0) inlineImageScale = 1.0f; // Create resized, tinted image matching font size and (text) color UIImage *imageMatchingFont = [inlineImage imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]; { // Font size NSDictionary *attributesForRange = [self attributesAtIndex:range.location effectiveRange:nil]; UIFont *fontForRange = [attributesForRange valueForKey:NSFontAttributeName]; CGSize imageSizeMatchingFontSize = CGSizeMake(inlineImage.size.width * (fontForRange.capHeight / inlineImage.size.height), fontForRange.capHeight); // Some scaling for prettiness CGFloat defaultScale = 1.4f; imageSizeMatchingFontSize = CGSizeMake(imageSizeMatchingFontSize.width * defaultScale, imageSizeMatchingFontSize.height * defaultScale); imageSizeMatchingFontSize = CGSizeMake(imageSizeMatchingFontSize.width * inlineImageScale, imageSizeMatchingFontSize.height * inlineImageScale); imageSizeMatchingFontSize = CGSizeMake(ceilf(imageSizeMatchingFontSize.width), ceilf(imageSizeMatchingFontSize.height)); // Text color UIColor *textColorForRange = [attributesForRange valueForKey:NSForegroundColorAttributeName]; // Make the matching image UIGraphicsBeginImageContextWithOptions(imageSizeMatchingFontSize, NO, 0.0f); [textColorForRange set]; [inlineImage drawInRect:CGRectMake(0 , 0, imageSizeMatchingFontSize.width, imageSizeMatchingFontSize.height)]; imageMatchingFont = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); } // Text attachment with image NSTextAttachment *textAttachment = [NSTextAttachment new]; textAttachment.image = imageMatchingFont; NSAttributedString *imageString = [NSAttributedString attributedStringWithAttachment:textAttachment]; [self replaceCharactersInRange:range withAttributedString:imageString]; } @end @implementation NSAttributedString (InlineImages) - (NSAttributedString *)attributedStringByReplacingOccurancesOfString:(NSString *)string withInlineImage:(UIImage *)inlineImage scale:(CGFloat)inlineImageScale { NSMutableAttributedString *attributedStringWithImages = [self mutableCopy]; [attributedStringWithImages.string enumerateOccurancesOfString:string usingBlock:^(NSRange substringRange, BOOL *stop) { [attributedStringWithImages replaceCharactersInRange:substringRange withInlineImage:inlineImage scale:inlineImageScale]; }]; return [attributedStringWithImages copy]; } @end 

    La solución del problema en el ejemplo simple es enter image description here

     let attachment = NSTextAttachment() attachment.image = UIImage(named: "qrcode") let iconStringdString = NSAttributedString(attachment: attachment) let fString = NSMutableAttributedString(string: "scan the ") let sString = NSAttributedString(string: "QR code received on your phone.") fString.append(iconStringdString) fString.append(sString) self.textLabel.attributedText = fString