Aunque la pregunta establece programáticamente, habiendo encontrado el mismo problema y prefiriendo trabajar en Interface Builder, pensé que podría ser útil agregar a las respuestas existentes con una solución de Interface Builder.
Lo primero es olvidar sizeToFit
. El diseño automático se encargará de esto en su nombre en función del tamaño del contenido intrínseco.
Por lo tanto, el problema es, ¿cómo hacer que una etiqueta se ajuste a su contenido con Auto Layout? Específicamente, porque la pregunta lo menciona, la altura. Tenga en cuenta que los mismos principios se aplican al ancho.
Comencemos con un ejemplo de UILabel que tiene una altura establecida en 41px de altura:
Como puede ver en la captura de pantalla de arriba, "This is my text"
tiene relleno arriba y abajo. Eso es un relleno entre la altura de UILabel, y su contenido, el texto.
Si ejecutamos la aplicación en el simulador, efectivamente, vemos lo mismo:
Ahora, seleccionemos UILabel en Interface Builder y echemos un vistazo a la configuración predeterminada en el inspector de tamaño:
Tenga en cuenta la restricción resaltada arriba. Esa es la prioridad de contenido que abraza . Como lo describe Erica Sadun en el excelente diseño automático de iOS desmitificado , esto es:
la forma en que una vista prefiere evitar el relleno adicional alrededor de su contenido principal
Para nosotros, con UILabel, el contenido central es el texto.
Aquí llegamos al corazón de este escenario básico. Le hemos dado a nuestra etiqueta de texto dos restricciones. Ellos entran en conflicto. Uno dice "la altura debe ser igual a 41 píxeles de alto" . El otro dice "abrace la vista a su contenido para que no tengamos ningún relleno adicional" . En nuestro caso, abrace la vista a su texto para que no tengamos ningún relleno adicional.
Ahora, con Auto Layout, con dos instrucciones diferentes que dicen hacer cosas diferentes, el tiempo de ejecución tiene que elegir uno u otro. No puede hacer las dos cosas. El UILabel no puede tener 41 píxeles de alto y no tiene relleno.
La forma en que esto se resuelve es especificando prioridad. Una instrucción debe tener mayor prioridad que la otra. Si ambas instrucciones dicen cosas diferentes y tienen la misma prioridad, se producirá una excepción.
Así que vamos a intentarlo. Mi restricción de altura tiene una prioridad de 1000 , que es obligatoria . La altura de abrazo del contenido es 250 , que es débil . ¿Qué sucede si reducimos la prioridad de restricción de altura a 249 ?
Ahora podemos ver que la magia comienza a suceder. Probemos en el sim:
¡Increíble! Contenido abrazado logrado. Solo porque la prioridad de altura 249 es menor que el contenido que abarca la prioridad 250 . Básicamente, digo que "la altura que especifico aquí es menos importante que la que especifiqué para el contenido abrazado" . Entonces, el contenido que abraza gana.
En pocas palabras, lograr que la etiqueta se ajuste al texto puede ser tan simple como especificar la restricción de altura o anchura y establecer correctamente esa prioridad en asociación con la restricción de prioridad de contenido de ese eje.
¡Saldrá haciendo el equivalente de ancho como ejercicio para el lector!
label.sizeToFit()
en Xcode / viewController, las restricciones eran suficientes. no estaba creando la etiqueta en Playground . Hasta ahora, la única manera que he encontrado para trabajar en juegos es hacerlabel.sizeToFit()