Esta es la segunda parte de un ciclo de artículos sobre cómo mejorar el rendimiento de las aplicaciones iOS.
Por qué AutoLayout podría estar ralentizando tu app y cómo solucionarlo
AutoLayout es la herramienta estándar para posicionar y dimensionar elementos UI en aplicaciones iOS. Es flexible y potente, pero no siempre es la opción más eficiente. Cuando la interfaz requiere ajustes dinámicos, como etiquetas que cambian de tamaño según su contenido, AutoLayout puede generar problemas de rendimiento, especialmente en dispositivos más antiguos.
Al principio, la diferencia en el rendimiento puede ser mínima. Pero a medida que la UI se vuelve más compleja, los efectos se hacen notorios: desplazamientos entrecortados, animaciones con retraso y una experiencia visual menos fluida.
La alternativa es usar layouts manuales con frames. En lugar de depender de AutoLayout, se calcula y establece manualmente la posición y el tamaño de los elementos de la interfaz. Esto requiere más líneas de código, pero mejora considerablemente la velocidad y la responsividad de la aplicación.
Por ejemplo, en una celda de pronóstico del clima, en lugar de definir múltiples restricciones de AutoLayout, se posicionan los elementos manualmente utilizando la propiedad frame
. Esto elimina el tiempo de procesamiento adicional causado por la resolución de restricciones, haciendo que las actualizaciones de UI sean mucho más rápidas.
Sin embargo, los layouts manuales son rígidos. Si cambian el tamaño de la celda o la fuente del texto, los valores deben ajustarse manualmente, lo que añade mantenimiento adicional.
Un método efectivo para manejar esto es deshabilitar la creación automática de restricciones en todos los elementos antes de definir su posición manualmente.
Para controlar cómo se ajustan etiquetas dentro de una celda, se puede calcular su tamaño antes de posicionarlas:
func getLabelSize(text: String, font: UIFont) -> CGSize {
let maxWidth = bounds.width - insets * 2
let textBlock = CGSize(width: maxWidth, height: CGFloat.greatestFiniteMagnitude)
let rect = text.boundingRect(with: textBlock, options: .usesLineFragmentOrigin,
attributes: [.font: font], context: nil)
return CGSize(width: ceil(rect.width), height: ceil(rect.height))
}
Este método permite que la etiqueta se adapte dinámicamente sin desperdiciar espacio o causar recortes en el texto.
Luego, se definen los marcos de los elementos dentro de la celda:
func messageLabelFrame() {
guard let text = messageLabel.text, !text.isEmpty else { return }
let messageLabelSize = getLabelSize(text: text, font: messageLabel.font)
let messageLabelX = avatarImageView.frame.maxX + insets
messageLabel.frame = CGRect(x: messageLabelX, y: insets, width: messageLabelSize.width, height: messageLabelSize.height)
}
Este principio se puede aplicar al resto de elementos en la celda, garantizando un posicionamiento óptimo sin depender de restricciones dinámicas de AutoLayout.
Una vez definidos estos métodos, se invocan dentro de layoutSubviews
para actualizar los frames cuando cambian los datos:
override func layoutSubviews() {
super.layoutSubviews()
messageLabelFrame()
timestampLabelFrame()
avatarImageFrame()
}
Además, se pueden crear setters para actualizar el contenido correctamente:
func setMessage(text: String) {
messageLabel.text = text
messageLabelFrame()
}
func setTimestamp(text: String) {
timestampLabel.text = text
timestampLabelFrame()
}
Esto garantiza que cada vez que se actualice el contenido, la UI refleje los cambios correctamente sin generar cálculos innecesarios.
Conclusión
Al prescindir de AutoLayout y adoptar layouts manuales con frames, eliminamos la sobrecarga generada por los cálculos automáticos de restricciones. Esto optimiza la fluidez de la interfaz, mejora el rendimiento y reduce los retrasos en aplicaciones con contenido dinámico.
Si bien esta técnica implica escribir más código y prestar atención a posibles cambios visuales, el beneficio en términos de velocidad y experiencia de usuario lo convierte en una estrategia valiosa para aplicaciones que requieren máxima eficiencia.
En Q2BSTUDIO, nos especializamos en el desarrollo de soluciones tecnológicas de alto rendimiento. Aplicamos metodologías optimizadas para garantizar aplicaciones rápidas, fluidas y escalables, asegurando que cada proyecto entregue la mejor experiencia al usuario sin comprometer la eficiencia.