iOS UILabel autoshrink por lo que word no trunca a dos líneas

Estoy intentando que el UILabel se encoja para que las palabras no se trunguen en la siguiente línea. No solo truncamiento de text al final del área de text.

Si tengo un cuadro que es 50×100, y quiero poner algo así como "estadounidense" en el cuadro a 25.0pt, termino recibiendo:

50px ------- |Ameri- | |can | |Beauty | 100px | | ------- 

La networkingucción del text no parece hacer nada durante esta situación, ya que aún cabe en el marco UILabel. Funciona bastante bien cuando el text es realmente largo como "Fábrica de choqueuete de Willie Wonka", pero no quiero truncamiento de palabras.

Este es el resultado ideal en ese escenario:

  50px -------- [American| |Beauty | 100px | | | | | | -------- 

¡Cualquier sugerencia sería súper apreciada!

Editar: SOLUCIÓN

Esto es lo que terminé haciendo gracias a la sugerencia en la respuesta a continuación. Funciona muy bien!

 - (CGFloat) calculateFromUILabel:(UILabel *)label { NSString *stringToMeasure = label.text; NSLog(@"FontSizeMeasurement.calculateFromUILabel() %@", stringToMeasure); NSRange range = NSMakeRange(0, 1); NSAttributedString *attributedString = label.attributedText; NSDictionary *attributes = [attributedString attributesAtIndex:0 effectiveRange:&range]; NSMutableCharacterSet *characterSet = [[NSCharacterSet whitespaceAndNewlineCharacterSet] mutableCopy]; [characterSet addCharactersInString:@"-"]; NSArray *words = [stringToMeasure componentsSeparatedByCharactersInSet:characterSet]; CGSize maxSize = CGSizeZero; NSMutableAttributedString *maxWidthString = nil; for(int i = 0; i < words.count; i++) { NSString *word = words[i]; CGSize wordSize = [word sizeWithAttributes:attributes]; if(wordSize.width > maxSize.width) { maxSize = wordSize; maxWidthString = [[NSMutableAttributedString alloc] initWithString:word attributes:attributes]; } } UIFont *font = [label.font copy]; while(maxSize.width > self.maxWidth) { font = [font fontWithSize:(font.pointSize-0.1)]; [maxWidthString addAttribute:NSFontAttributeName value:font range:NSMakeRange(0, maxWidthString.length)]; maxSize = [maxWidthString size]; } return font.pointSize; } 

No puedo pensar en nada que esté incorporado directamente. Entonces sugiero:

Dividir la cadena en componentes por [NSCharacterSet +whitespaceAndNewlineCharacterSet] y [NSString -componentsSeparatedByCharactersInSet:] . Yo consideré recomendar el NSLinguisticTagger nivel NSLinguisticTagger para que salga palabras completas, pero eso no permitiría cosas como palabras con dos puntos al final.

De esas palabras, encuentre la tipográficamente más grande usando la adición de NSString -sizeWithAttributes: (en iOS 7) o -sizeWithFont: (debajo de 6 o inferior). Va a asumir que el más grande seguirá siendo el más grande a medida que networkinguzca el tamaño de la fuente, lo que creo que siempre será cierto porque Apple no hace sugerencias de fonts agresivas.

Si esa palabra ya es less ancha que el ancho de su vista, habrá terminado. Solo muestra la cadena.

De lo contrario, utilice una búsqueda binaria rápida, consultando repetidamente el tamaño, hasta que encuentre el tamaño de letra más pequeño que necesite dentro de la precisión que crea conveniente (0.1 de un punto me parece razonable pero obtendrá el punto). Luego, muestre la secuencia completa a ese tamaño.

Hice una extensión Swift de UILabel. Simplemente llame al método a la label después de establecer los límites y el text.

 extension UILabel { func fitToAvoidWordWrapping(){ // adjusts the font size to avoid long word to be wrapped // get text as NSString let text = self.text ?? "" as NSString // get array of words separate by spaces let words = text.componentsSeparatedByString(" ") as! [NSString] // I will need to find the largest word and its width in points var largestWord : NSString = "" var largestWordWidth : CGFloat = 0 // iterate over the words to find the largest one for word in words{ // get the width of the word given the actual font of the label let wordSize = word.sizeWithAttributes([NSFontAttributeName : self.font]) let wordWidth = wordSize.width // check if this word is the largest one if wordWidth > largestWordWidth{ largestWordWidth = wordWidth largestWord = word } } // now that I have the largest word, networkinguce the label's font size until it fits while largestWordWidth > self.bounds.width && self.font.pointSize > 1{ // networkinguce font and update largest word's width self.font = self.font.fontWithSize(self.font.pointSize - 1) let largestWordSize = largestWord.sizeWithAttributes([NSFontAttributeName : self.font]) largestWordWidth = largestWordSize.width } } } 

Traducción de SWIFT 3 de la extensión anterior. ¡Funciona de maravilla!

 extension UILabel { func fitToAvoidWordWrapping(){ // adjusts the font size to avoid long word to be wrapped // get text as NSString let text = self.text ?? ("" as NSString) as String // get array of words separate by spaces let words = text.components(separatedBy: " ") // I will need to find the largest word and its width in points var largestWord : NSString = "" var largestWordWidth : CGFloat = 0 // iterate over the words to find the largest one for word in words{ // get the width of the word given the actual font of the label let wordSize = word.size(attributes: [NSFontAttributeName : self.font]) let wordWidth = wordSize.width // check if this word is the largest one if wordWidth > largestWordWidth{ largestWordWidth = wordWidth largestWord = word as NSString } } // now that I have the largest word, networkinguce the label's font size until it fits while largestWordWidth > self.bounds.width && self.font.pointSize > 1{ // networkinguce font and update largest word's width self.font = self.font.withSize(self.font.pointSize - 1) let largestWordSize = largestWord.size(attributes: [NSFontAttributeName : self.font]) largestWordWidth = largestWordSize.width } } }