¿Con qué debería reemplazar el método obsoleto sizeWithFont:?

Tengo un método que me da el tamaño perfecto para una UITextView dada una longitud de cadena (con el tamaño de letra 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 se trata de un método de advertencia que dice que no debería usar ‘sizeWithFont: contrainedToSize: lineBreakMode’.

Ahora dice que debería estar usando -boundingRectWithSize: options: attributes: context:

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

Tengo tres preguntas:

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

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

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

    Después de una hora de error de prueba, logré que funcione:

     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 respuesta a continuación: En iOS 7 y posterior, este método devuelve tamaños fraccionarios (en el componente de tamaño del CGRect devuelto); para usar una vista de tamaño devuelto a tamaño, debe usar elevar su valor al número entero más alto más cercano utilizando la función ceil. Se recomienda usar la función ceilf .

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

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

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

    En ese sentido, si solo estuvieras soportando iOS 6 e iOS 7, definitivamente cambiaría todo el tamaño de tu sizeWithFont:... al boundingRectWithSize de NSAttributeString. ¡Te ahorrará muchos dolores de cabeza si tienes una extraña caja de esquina con múltiples hilos! Así es como convertí el tamaño 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; 

    Tenga en cuenta que 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 una vista de tamaño devuelto a tamaño, debe usar elevar su valor al número entero más alto más cercano utilizando la función ceil.

    Para sacar la altura o el ancho calculados que se usarán para dimensionar vistas, usaría:

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

    Para el problema de salto de línea:

     - (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); } 

    Versión rápida 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 de la siguiente manera …

     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