objective-c nsstring deprecated

objective c - ¿Con qué debo reemplazar el método sizeWithFont: obsoleto?



objective-c nsstring (4)

Creo que la función estaba en desuso porque esa serie de funciones NSString + UIKit se basaban en la biblioteca UIStringDrawing, que no era segura para subprocesos. Si intentaste ejecutarlos no en el hilo principal (como cualquier otra funcionalidad de UIKit), obtendrás comportamientos impredecibles. En particular, si ejecutó la función en varios subprocesos simultáneamente, probablemente bloqueará su aplicación. Es por eso que en iOS 6, introdujeron el método boundingRectWithSize:... para NSAttributedStrings. Esto se creó sobre las bibliotecas NSStringDrawing y es seguro para subprocesos.

Si observa la nueva función boundingRectWithSize:... NSString, solicita una matriz de atributos de la misma manera que una NSAttributeString. Si tuviera que adivinar, esta nueva función NSString en iOS 7 es simplemente una envoltura para la función NSAttributeString de iOS 6.

En esa nota, si solo estuvieras soportando iOS 6 y iOS 7, definitivamente cambiaría todo el tamaño de tu sizeWithFont:... a la NSAttributeString''s boundingRectWithSize . ¡Te ahorrará muchos dolores de cabeza si tienes un extraño estuche de esquina con subprocesos múltiples! Aquí es cómo convertí sizeWithFont de sizeWithFont:constrainedToSize: ::

Lo que solía ser:

NSString *text = ...; CGFloat width = ...; UIFont *font = ...; CGSize size = [text sizeWithFont:font constrainedToSize:CGSizeMake(width, CGFLOAT_MAX)];

Puede ser reemplazado por:

NSString *text = ...; CGFloat width = ...; UIFont *font = ...; NSAttributedString *attributedText = [[NSAttributedString alloc] initWithString:text attributes:@ { NSFontAttributeName: font }]; CGRect rect = [attributedText boundingRectWithSize:CGSizeMake(width, CGFLOAT_MAX) options:NSStringDrawingUsesLineFragmentOrigin context:nil]; CGSize size = rect.size;

Por favor, tenga en cuenta la documentación menciona:

En iOS 7 y versiones posteriores, este método devuelve tamaños fraccionarios (en el componente de tamaño del CGRect devuelto); para usar un tamaño devuelto a las vistas de tamaño, debe usar aumentar su valor al número entero más cercano utilizando la función ceil.

Por lo tanto, para extraer la altura o el ancho calculados que se usarán para dimensionar las vistas, usaría:

CGFloat height = ceilf(size.height); CGFloat width = ceilf(size.width);

Tengo un método que me da el tamaño perfecto para un UITextView dada una longitud de cadena (con el tamaño de fuente correcto correspondiente):

- (NSInteger) heightOfLabel:(NSString*) string { CGSize maximumLabelSize = CGSizeMake([[UIScreen mainScreen] bounds].size.width - 40, FLT_MAX); CGSize expectedLabelSize = [[NSString stringTrimmedForLeadingAndTrailingWhiteSpacesFromString:string] sizeWithFont:[UIFont systemFontOfSize:15] constrainedToSize:maximumLabelSize lineBreakMode:NSLineBreakByWordWrapping]; return expectedLabelSize.height + 5; }

De hecho, todavía me da un ajuste perfecto, incluso en iOS7. Aunque ahora viene con un método de advertencia que dice que no debería usar ''sizeWithFont: contrainedToSize: lineBreakMode''.

Ahora dice que debería usar -boundingRectWithSize: opciones: atributos: contexto:

Este método no es nuevo para iOS7 y, por lo tanto, creo que está bien pedirlo en el desbordamiento de pila, en lugar de ir al foro oficial de desarrolladores de Apple.

Tengo tres preguntas:

1) Debido a que está en desuso, ¿eso significa que definitivamente debería reemplazarlo, a pesar de que aún funciona?

2) He probado diferentes métodos de boundingRectWithSize: con varias variables, pero nunca es perfecto, siempre parece estar ligeramente fuera (como lo señalan muchas preguntas de stackoverflow). ¿Existe un reemplazo perfecto con este método que no está en desuso y que hace exactamente eso? ¿Lo mismo que mi método anterior con una molestia mínima?

3) ¿Por qué eliminar este método? ¿Es debido a la superposición con este otro método?


Después de una hora de error de prueba logré que funcionara:

CGSize maximumLabelSize = CGSizeMake(tableView.width, MAXFLOAT); NSStringDrawingOptions options = NSStringDrawingTruncatesLastVisibleLine | NSStringDrawingUsesLineFragmentOrigin; NSDictionary *attr = @{NSFontAttributeName: [UIFont systemFontOfSize:15]}; CGRect labelBounds = [string boundingRectWithSize:maximumLabelSize options:options attributes:attr context:nil];

Actualizar:

Como el Sr. T menciona en la respuesta a continuación: En iOS 7 y versiones posteriores, este método devuelve tamaños fraccionarios (en el componente de tamaño del CGRect devuelto); para usar un tamaño devuelto a las vistas de tamaño, debe usar aumentar su valor al número entero más cercano utilizando la función ceil. Se recomienda el uso de la función ceilf .

CGFloat height = ceilf(labelBounds.size.height);


Versión veloz de la respuesta de Alejandro de Noruega ...

func heightNeededForText(text: NSString, withFont font: UIFont, width: CGFloat, lineBreakMode:NSLineBreakMode) -> CGFloat { let paragraphStyle = NSMutableParagraphStyle() paragraphStyle.lineBreakMode = lineBreakMode let size: CGSize = text.boundingRectWithSize(CGSizeMake(width, CGFloat.max), options: [.UsesLineFragmentOrigin, .UsesFontLeading], attributes: [ NSFontAttributeName: font, NSParagraphStyleAttributeName: paragraphStyle], context: nil).size//text boundingRectWithSize:CGSizeMake(width, CGFLOAT_MA return ceil(size.height); }

En el código donde desea obtener la altura, simplemente llame al método como se muestra a continuación ...

let size = self.heightNeededForText(text as NSString, withFont: UIFont.systemFontOfSize(15.0), width: scrollView.frame.size.width - 20, lineBreakMode: NSLineBreakMode.ByWordWrapping) //Can edit the font size and LinebreakMode


Para el problema de rotura

- (CGFloat)heightNeededForText:(NSString *)text withFont:(UIFont *)font width:(CGFloat)width lineBreakMode:(NSLineBreakMode)lineBreakMode { NSMutableParagraphStyle * paragraphStyle = [[NSMutableParagraphStyle alloc] init]; paragraphStyle.lineBreakMode = lineBreakMode; CGSize size = [text boundingRectWithSize:CGSizeMake(width, CGFLOAT_MAX) options:(NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading) attributes:@{ NSFontAttributeName: font, NSParagraphStyleAttributeName: paragraphStyle } context:nil].size; return ceilf(size.height); }