Líneas que faltan desde UILabel alto al incrustar NSTextAttachment

Puedo crear un NSAttributedString varias líneas utilizando caracteres de nueva línea escapados ( @"\n" ). Con iOS 7, ahora puedo incrustar un UIImage dentro de cadenas atribuidas (a través de NSTextAttachment ).

He notado que cada vez que configuro el text attributedText de una UILabel a una cadena atribuida de varias líneas con una image incrustada, la cantidad de líneas realmente mostrada es inversamente proporcional a la altura de la label. Por ejemplo, cuando la altura de la label es 80, aparecen dos líneas; cuando la altura es de alnetworkingedor de 100, solo aparece la segunda línea; cuando la altura es de aproximadamente 130, no aparece nada.

Este problema se produjo al tratar de ubicar múltiples UILabels lado a lado dentro de UITableViewCell y hacer que las tags crezcan (verticalmente) con la altura de la celda.

¿Alguien puede explicar por qué esto está sucediendo? ¿Alguien sabe soluciones que no implican hacer que UILabel sea más pequeño?


Código de muestra:

 @implementation SOViewController - (void)viewDidLoad { [super viewDidLoad]; NSMutableAttributedString *text1 = [[NSMutableAttributedString alloc] init]; [text1 appendAttributedString:[[NSAttributedString alloc] initWithString:@"Line 1\n"]]; [text1 appendAttributedString:[[NSAttributedString alloc] initWithString:@"Line 2"]]; UIImage *image = [UIImage imageNamed:@"17x10"]; //some PNG image (17px by 10px) NSTextAttachment *attachment = [[NSTextAttachment alloc] init]; attachment.image = image; attachment.bounds = CGRectMake(0, 0, image.size.width, image.size.height); NSMutableAttributedString *text2 = [[NSMutableAttributedString alloc] init]; [text2 appendAttributedString:[[NSAttributedString alloc] initWithString:@"Line 1\n"]]; [text2 appendAttributedString:[NSAttributedString attributedStringWithAttachment:attachment]]; [text2 appendAttributedString:[[NSAttributedString alloc] initWithString:@"Line 2"]]; CGFloat margin = 20; //shows both lines when height == 80 //shows line 2 when 90 <= height <= 120 //shows nothing when height == 130 CGFloat height = ???; CGFloat width = 200; UILabel *label1 = [[UILabel alloc] initWithFrame:CGRectMake(margin, margin, width, height)]; UILabel *label2 = [[UILabel alloc] initWithFrame:CGRectMake(margin, margin + height, width, height)]; [self.view addSubview:label1]; [self.view addSubview:label2]; label1.backgroundColor = [UIColor orangeColor]; label2.backgroundColor = [UIColor blueColor]; label2.textColor = [UIColor whiteColor]; label1.numberOfLines = 0; label2.numberOfLines = 0; label1.attributedText = text1; label2.attributedText = text2; UIImageView *imageView = [[UIImageView alloc] initWithImage:image]; imageView.frame = CGRectMake(margin + width, margin + height, image.size.width, image.size.height); [self.view addSubview:imageView]; } @end 

… Ponga esto en el controller de vista pnetworkingeterminado de una "aplicación de vista única". (Puedes elegir tu propia image.)

Realmente no tiene nada que ver con el NSTextAttachment. Es que en iOS 7 lanzado hasta el momento, UILabel no es muy bueno dibujando cadenas atribuidas. Una cadena atribuida simple con algún subrayado y un estilo de párrafo centrado aparecerá en blanco o parcialmente en blanco en un UILabel; la misma cadena atribuida llega bien en un UITextView.

Entonces, una solución por ahora es: Use UITextView en su lugar. Esta es en realidad una solución bastante buena porque, en iOS 7, UITextView es solo un envoltorio de la stack de Kit de text. Entonces dibuja la cadena atribuida de una manera directa. No se ve obstaculizada por la relación que no tiene lugar con Web Kit que tenía en versiones anteriores de iOS.

Por otro lado, también encontré una solución para este error de UILabel; tienes que juguetear con el número de líneas de la label y la cadena de forma que se bloquee el text hasta la parte superior de la label: ver mi respuesta aquí: https://stackoverflow.com/a/19409962/341994

O puede esperar a que Apple arregle el error y mantenga los dedos cruzados. EDIT: en iOS 7.1, parece que el error será corregido y no se necesitará ninguna solución.

Parece ser un error en UILabel . El mismo código funciona bien cuando se usa UITextView lugar de UILabel (el tamaño de fuente pnetworkingeterminado de UITextView es diferente, así que lo probé en diferentes alturas).

¿Intentaste get la altura real del text usando el método boundingRectWithSize:

 NSAttributedString *text; CGFloat width = 200; CGRect rect = [text boundingRectWithSize:CGSizeMake(width, CGFLOAT_MAX) options:NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading context:nil]; CGFloat height = rect.size.height; 

Encontré otra solución para este error, que es lo suficientemente diferente de mi respuesta anterior que estoy proporcionando como otra respuesta: deje que la label establezca su propia altura.

En este código, estoy eliminando la restricción de altura de una label con una restricción de ancho fijo, y reemplazándola por una restricción mayor que la altura (y estoy seguro de que hay otras forms de lograr el mismo resultado):

 [self.lab removeConstraint:self.labelHeight]; [self.lab addConstraint: [NSLayoutConstraint constraintWithItem:self.lab attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationGreaterThanOrEqual toItem:nil attribute:0 multiplier:1 constant:20]]; 

¡Esa label muestra correctamente cada cadena atribuida que lanzo en ella! Por supuesto, pierdes el centrado vertical automático de la cadena, pero esa es la fuente completa del error, por lo que perderlo no es tan terrible.