¿Cómo truncar un NSString basado en el ancho gráfico?

En UILabel hay funcionalidad para truncar tags usando diferentes técnicas de truncamiento (UILineBreakMode). En NSString UIKit Additions hay una funcionalidad similar para dibujar cadenas.

Sin embargo, no encontré ninguna forma de acceder a la cadena truncada real. ¿Hay alguna otra manera de get una cadena truncada basada en el ancho (gráfico) para una fuente dada?

Me gustaría tener una categoría en NSString con este método:

-(NSString*)stringByTruncatingStringWithFont:(UIFont *)font forWidth:(CGFloat)width lineBreakMode:(UILineBreakMode)lineBreakMode 

Una opción es probar diferentes tamaños haciendo un bucle hasta get el ancho correcto. Es decir, comience con la cadena completa, si eso es más amplia de lo que necesita, reemplace los dos últimos caracteres con un carácter de puntos suspensivos. Loop hasta que sea lo suficientemente estrecho.

Si crees que estarás trabajando con cadenas largas, puedes search binarias en tu path hacia el punto de truncamiento para que sea un poco más rápido.

 - (NSString*)stringByTruncatingStringWithFont:(UIFont *)font forWidth:(CGFloat)width lineBreakMode:(UILineBreakMode)lineBreakMode { NSMutableString *resultString = [[self mutableCopy] autorelease]; NSRange range = {resultString.length-1, 1}; while ([resultString boundingRectWithSize:CGSizeMake(FLT_MAX, FLT_MAX) options:NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading attributes:attributes context:nil].size.width > width) { // delete the last character [resultString deleteCharactersInRange:range]; range.location--; // replace the last but one character with an ellipsis [resultString replaceCharactersInRange:range withString:truncateReplacementString]; } return resultString; } 

Tenga en count que desde iOS 6, este método ya no es seguro para ejecutarse en subprocesss de background.