Texto, imágenes y los VStack, fundamentales para crear las bases de nuestras aplicaciones en SwiftUI
- 👤 Andrés Cruz
En esta entrada, vamos a seguir trabajando en la creación de nuestras aplicaciones en SwiftUI; anteriormente hablamos un poco de SwiftUI, que es el nuevo framework de Apple para crear nuestras aplicaciones de manera declarativa; en otras palabras, SwiftUI es el Flutter de Google pero al mejor estilo de Apple:
Primeros pasos con SwiftUI para construir tu interfaz declarativa.
Además de esto vimos cual es el ambiente que debemos emplear para poder desarrollar nuestras primeras apps, que viene siendo xCode 11 a partir de iOS 13, algunos ejemplos de listas, foreach, etc para acostumbrarnos a su sintaxis, su forma de organización y algunos recursos para empezar a trabajar con SwiftUI.
En resumen Swiftui es una simple interfaz declarativa con la cual podemos construir nuestras interfaces en el ecosistema de Apple.
SwiftUI es el framework declarativo de Apple para crear interfaces de usuario en iOS, macOS y más. Si vienes de Android, Flutter o incluso del UIKit clásico, al principio puede parecer “demasiado simple”… hasta que empiezas a chocar con errores típicos como no poder usar un Text y un Image juntos, textos que se cortan o imágenes que rompen todo el layout.
En esta guía voy a mostrarte, paso a paso, cómo combinar Text, Image y VStack en SwiftUI, resolviendo los problemas reales que aparecen cuando empiezas.
Qué es SwiftUI y por qué usar VStack para organizar vistas
SwiftUI se basa en un principio clave: todo es una vista y las vistas se componen entre sí. No hay XML, no hay storyboards separados. En el mismo archivo defines la lógica y la interfaz.
En mi caso, lo que más me llamó la atención al inicio fue que con muy poco código ya estás renderizando una UI real, algo muy distinto a UIKit o incluso a Android con layouts y más similar a Flutter.
Creando una app básica con SwiftUI
Vamos a empezar a crear una app bastante sencilla la cual consta de algunos textos, una imagen central y un elemento contenedor para colocar todo esto y vamos a crear un texto, para eso empleamos el struct Text:
import SwiftUI
struct texto_imagen: View {
var body: some View {
Text("Hello World")
}
}Y obtenemos:

Aquí empieza todo, como ves, esto es el porqué de que SwiftUI es un framework de interfaz declarativa, ya que en el mismo archivo en el cual estamos declarando la funcionalidad (como nuestro controlador), también este mismo elemento de vista hace desplegar lo que sería una interfaz, es decir ese Text al cual le podemos aplicar alguna lógica hace también que se renderice un texto en nuestra interfaz sin necesidad de aplicar un archivo de vista aparte como sería en Android con los layout o en Swift clásico con el Main Storyboard.
El problema inicial: Text e Image no pueden ir solos en el body
Cómo ves vemos nuestro texto en nuestra pantalla; ahora queremos agregar una simple imagen; para eso empleamos el Image especificando la imagen que debe de estar cargada en la carpeta Assets.xcassets de la manera tradicional, luego la referenciamos por el nombre y listo; pensarías que podemos hacer lo siguiente:

import SwiftUI
struct texto_imagen: View {
var body: some View {
Image("final_udemy")
Text("Hello World")
}
}Y obtenemos un error:

Esto es muy común cuando empiezas. A mí me pasó de inmediato y la reacción típica es pensar que el problema está en la imagen o en el texto… pero no.
Por qué SwiftUI exige una vista raíz
El body solo puede devolver una vista. Si quieres más de una, necesitas un contenedor. Aquí es donde entran los Stacks:
- VStack → vistas en vertical
- HStack → vistas en horizontal
- ZStack → vistas superpuestas
Usando VStack para combinar Text e Image correctamente
Pero esto nos dará un error ya que no podemos emplear múltiples elementos en la raíz, para eso necesitamos un elemento raíz, un elemento que nos permita agregar otros struct así como en Flutter, empleamos -por ejemplo- el widget Column para agregar un listado de widgets, que en otras palabras significa, uno o más widgets; aquí también podemos hacer lo mismo y emplear un elemento contenedor.
En este caso como queremos colocar todo como si fuera una pila, es decir, uno encima del otro vamos a emplear lo que sería un contenedor de tipo VStack y dentro del mismo, el código de nuestra imagen y el texto:
import SwiftUI
struct texto_imagen: View {
var body: some View {
VStack {
Image("final_udemy")
Text("Hello World")
}
}
}
En este caso coloque una imagen de mi curso en Udemy en el cual enseñamos a crear nuestras primeras apps móviles con Android e iOS y conectarlas a una Rest Api.
Modificadores sobre nuestros elementos de vista
Aquí viene lo bueno, desde nuestro archivo, podemos llamar a funciones con parámetros los cuales nos permiten alterar el estilo, posición y comportamiento de nuestros elementos; estos mismos se conocer como modificadores ya que permiten "modificar" o variar el estilo, posición y/o comportamiento de nuestros elementos de vista que hoy hemos visto tres:
TextImageVStak
Añadiendo textos multilínea en SwiftUI con lineLimit
Al agregar un título y una descripción más larga, aparece otro problema típico:
el texto se corta y solo muestra una línea.
VStack {
Text("Aprende a crear apps en Android e iOS con una RestAPI en PHP")
Image("final_udemy")
Text("Crear tus apps nativas para Android e iOS y conectarlas a una Rest API...")
}Solución: lineLimit y font:
Text("Aprende a crear apps en Android e iOS con una RestAPI en PHP")
.lineLimit(3)
.font(.title)
Text("Crear tus apps nativas para Android e iOS y conectarlas a una Rest API...")
.lineLimit(nil)
.font(.body)Vamos con nuestro ejemplo.
Ahora, antes de entrar con algunos modificadores vamos a querer agregar una título a nuestra imagen y una descripción más original, y con nuestro VStack esto nos viene perfecto:
import SwiftUI
struct texto_imagen: View {
var body: some View {
VStack {
Text("Aprende a crear apps en Android e iOS con una RestAPI en PHP")
Image("final_udemy")
Text("Crear tus apps nativas para Android e iOS y conectalas a una Rest Api en CodeIgniter 3: módulo de gestión con jQuery, Bootstrap 4, roles de usuarios, Retrofit, Alamofire, peticiones Post, Get, creación de Rest Api, primeros pasos con Kotlin y Swift, listados (RecyclerView, TableView), SwiftUI, uploads de avatares desde las apps móviles y mucho más")
}
}
}
Como puedes ver, se va apilando todo perfectamente; pero como puedes ver tenemos varios problemas, el primero de ellos es que se corta el texto y solo aparece una línea, el siguiente sería que el texto superior y el inferior tienen la misma presentación; vamos a variarle un poco con el modificador/función de font para variar el texto y otro modificador para indicar que presente el contenido en varias líneas de ser necesario:
import SwiftUI
struct texto_imagen: View {
var body: some View {
VStack {
Text("Aprende a crear apps en Android e iOS con una RestAPI en PHP")
.lineLimit(3)
.font(.title)
Image("final_udemy")
Text("Crear tus apps nativas para Android e iOS y conectalas a una Rest Api en CodeIgniter 3: módulo de gestión con jQuery, Bootstrap 4, roles de usuarios, Retrofit, Alamofire, peticiones Post, Get, creación de Rest Api, primeros pasos con Kotlin y Swift, listados (RecyclerView, TableView), SwiftUI, uploads de avatares desde las apps móviles y mucho más")
.lineLimit(nil)
.font(.body)
}
}
}
Como puedes ver, aparece algo mejor, pero aun tenemos algunos problemas pero antes de eso, como puedes ver, agregamos un par de modificadores, uno para indicar el tipo de letra, pero eres libre de explorar y probar distintas combinaciones, pero como puedes ver, la misma recibe distintos parámetros y algunos valores como lo son body, title, largeTitlee, etc. Los cuales varían de manera automática la presentación de nuestro texto.
En cuanto a las líneas de texto, ahora puedes ver que para la descripción ahora se presenta en varias líneas, y esto lo logramos con el modificador lineLimit que recibe un número que indica el número de líneas máximo que tendrá el texto, o nil para que iOS aplique la cantidad de líneas sobre nuestros elementos.
Vamos a resolver el problema con los textos e imágenes, como puedes ver, la imagen es muy grande y estira nuestro contenedor, lo que produce que también no se vea completamente en la pantalla, esto podemos arreglarlo indicando un tamaño a la imagen; para eso empleamos el modificador frame:
struct texto_imagen: View {
var body: some View {
VStack {
Text("Aprende a crear apps en Android e iOS con una RestAPI en PHP")
.lineLimit(3)
.font(.title)
Image("final_udemy")
.resizable()
.frame(width: 375, height: 211)
Text("Crear tus apps nativas para Android e iOS y conectalas a una Rest Api en CodeIgniter 3: módulo de gestión con jQuery, Bootstrap 4, roles de usuarios, Retrofit, Alamofire, peticiones Post, Get, creación de Rest Api, primeros pasos con Kotlin y Swift, listados (RecyclerView, TableView), SwiftUI, uploads de avatares desde las apps móviles y mucho más")
.lineLimit(nil)
.font(.body)
}
}
}
Cómo cambiar el tamaño de una Image en SwiftUI
También aplicamos el modificador resizable que tiene que venir acompañado del modificador frame para indicar que queremos reescalar la imagen; como tarea, comenta o elimina temporalmente el modificador resizable y verás el comportamiento.
Otro clásico: la imagen es gigante y estira toda la vista.
Ahora vemos todo mucho mejor que antes, ya al menos tiene mejor aspecto nuestra aplicación, sin embargo ahora todo está como que muy pegado, vamos a aplicar otro modificados pero esta vez sobre nuestra imagen ya que es nuestro elemento central y de esta forma no tenemos que aplicar un padding para cada uno de los textos; también aplicaremos un padding a nuestro contenedor:
struct texto_imagen: View {
var body: some View {
VStack {
Text("Aprende a crear apps en Android e iOS con una RestAPI en PHP")
.lineLimit(3)
.font(.title)
Image("final_udemy")
.resizable()
.frame(width: 375, height: 211)
.padding()
Text("Crear tus apps nativas para Android e iOS y conectalas a una Rest Api en CodeIgniter 3: módulo de gestión con jQuery, Bootstrap 4, roles de usuarios, Retrofit, Alamofire, peticiones Post, Get, creación de Rest Api, primeros pasos con Kotlin y Swift, listados (RecyclerView, TableView), SwiftUI, uploads de avatares desde las apps móviles y mucho más")
.lineLimit(nil)
.font(.body)
}.padding()
}
}
Aplicando padding y espaciado en VStack
Con tan solo colocar padding que como puedes ver corresponde a otro modificador, se aplica un margen de manera automática, pero el mismo puede recibir distintos valores que indican la cantidad de puntos que tendrá el padding; por ejemplo 30 puntos para aplicarlos en cada uno de sus lados, es decir en el top, left, right y bottom:
struct texto_imagen: View {
var body: some View {
VStack {
Text("Aprende a crear apps en Android e iOS con una RestAPI en PHP")
.lineLimit(3)
.font(.title)
Image("final_udemy")
.resizable()
.frame(width: 375, height: 211)
.padding(30)
Text("Crear tus apps nativas para Android e iOS y conectalas a una Rest Api en CodeIgniter 3: módulo de gestión con jQuery, Bootstrap 4, roles de usuarios, Retrofit, Alamofire, peticiones Post, Get, creación de Rest Api, primeros pasos con Kotlin y Swift, listados (RecyclerView, TableView), SwiftUI, uploads de avatares desde las apps móviles y mucho más")
.lineLimit(nil)
.font(.body)
}.padding()
}
}El mismo al igual que todos los modificadores reciben distintos constructores los cuales tu eres libre de explorar.
Siempre recuerda ayudarte con el autocompletado y las sugerencias para los parámetros y elementos de vista que ofrece xCode para desarrollar tus aplicaciones en SwiftUI y en general.
Modificadores en SwiftUI: orden y buenas prácticas
Los modificadores son funciones que devuelven nuevas vistas. Por eso:
- El orden sí importa
- Cada modificador transforma el resultado del anterior
Un buen consejo (que me ahorró tiempo):
usa el autocompletado de Xcode. Ahí descubres opciones como .largeTitle, .padding(.horizontal) o .frame(maxWidth:).
Resultado final y vista completa
Al final, con un solo archivo y pocas líneas, tienes una interfaz completa, clara y funcional. En mi caso, esto fue lo que terminó de convencerme de que SwiftUI realmente acelera el desarrollo, sobre todo para prototipos y apps sencillas.
FAQs rápidas
- ¿Cómo poner Text e Image juntos en SwiftUI?
- Usando un contenedor como VStack o HStack.
- ¿Por qué SwiftUI no permite varias vistas en el body?
- Porque el body debe devolver una sola vista raíz.
- ¿Cómo hacer que un Text sea multilínea?
- Con .lineLimit(nil) o un número específico de líneas.
- ¿Cómo cambiar el tamaño de una Image?
- Usando .resizable() junto con .frame().
Conclusión
Con este sencillo ejemplo, hemos podido crear una sencilla aplicación que aunque no es la más funcional del mundo, pudimos ver que con pocas líneas de código y con un único archivo podemos construir interfaces completas sin mucho esfuerzo, aprendimos a emplear algunos elementos de vista así como sus modificadores más básicos
En resumen:
- Usar Text e Image en SwiftUI
- Resolver el error de múltiples vistas en el body
- Organizar contenido con VStack
- Crear textos multilínea con lineLimit
- Redimensionar imágenes correctamente
- Mejorar el layout con padding
No es la app más compleja del mundo, pero refleja exactamente los problemas reales que aparecen al empezar. En próximas guías puedes llevar esto más lejos con listas, ForEach, navegación y componentes reutilizables.
En próximas entradas veremos como potencias más todo esto y también nuevas estructuras y elementos de vista; en la siguiente entrada veremos cómo crear listados y los foreach y otros aspectos de interés.
El siguiente paso, aprede el uso de los diseños de pilas con Stack, VStack y ZStack en SwiftUI.
Acepto recibir anuncios de interes sobre este Blog.
Vamos a crear una sencilla aplicación que consta de un contenedor con VStack, una imagen y textos empleando SwiftUI, además aplicaremos modificadores para variar la fuente, espaciado, padding, etc.