Reemplazo para sizeWithFont obsoleto: ¿en iOS 7?

Resuelto James Kuang asked hace 10 años • 20 respuestas

En iOS 7, sizeWithFont:ahora está en desuso. ¿ Cómo paso ahora el objeto UIFont al método de reemplazo sizeWithAttributes:?

James Kuang avatar Sep 19 '13 21:09 James Kuang
Aceptado

Utilice sizeWithAttributes:en su lugar, que ahora requiere una extensión NSDictionary. Pase el par con la clave UITextAttributeFonty su objeto de fuente de esta manera:

CGRect rawRect = {};
rawRect.size = [string sizeWithAttributes: @{
    NSFontAttributeName: [UIFont systemFontOfSize:17.0f],
}];

// Values are fractional -- you should take the ceil to get equivalent values
CGSize adjustedSize = CGRectIntegral(rawRect).size;
James Kuang avatar Sep 19 '2013 14:09 James Kuang

Creo que la función quedó obsoleta porque esa serie de NSString+UIKitfunciones ( sizewithFont:..., etc.) se basaban en la UIStringDrawingbiblioteca, que no era segura para subprocesos. Si intenta ejecutarlos no en el hilo principal (como cualquier otra UIKitfuncionalidad), obtendrá 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 boundingRectWithSize:...método para NSAttributedString. Esto se construyó sobre las NSStringDrawingbibliotecas y es seguro para subprocesos.

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

En ese sentido, si solo fueras compatible con iOS 6 y iOS 7, definitivamente cambiaría todos tus archivos NSString sizeWithFont:...a NSAttributeString boundingRectWithSize. ¡Te ahorrará muchos dolores de cabeza si tienes un caso de esquina extraño con subprocesos múltiples! Así es como convertí NSString sizeWithFont:constrainedToSize::

Lo que solía ser:

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

Se puede reemplazar con:

NSString *text = ...;
CGFloat width = ...;
UIFont *font = ...;
NSAttributedString *attributedText =
    [[NSAttributedString alloc] initWithString:text 
                                    attributes:@{NSFontAttributeName: font}];
CGRect rect = [attributedText boundingRectWithSize:(CGSize){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 valor devuelto CGRect); Para usar un tamaño devuelto para dimensionar vistas, debe usar aumentar su valor al entero superior más cercano usando la función ceil.

Entonces, para extraer la altura o el ancho calculado que se usará para dimensionar las vistas, usaría:

CGFloat height = ceilf(size.height);
CGFloat width  = ceilf(size.width);
Mr. T avatar Sep 23 '2013 03:09 Mr. T