Domina Swift resultBuilder: cómo el patrón Builder evolucionó hasta la sintaxis del lenguaje
¿Pensaste esto la primera vez que viste SwiftUI?
«Espera, ¿cómo puede funcionar con solo enumerar varias vistas dentro de VStack { Text("A"); Text("B") }?»
Al principio parece magia. No hay punto y coma, comas ni return, pero todo se ensambla automáticamente.
La identidad de esa magia es Swift resultBuilder.
En resumen, resultBuilder convierte el patrón Builder que antes implementábamos manualmente como patrón de diseño en una característica del lenguaje, para que el compilador lo escriba por nosotros. Sustituye el código repetitivo de ensamblar objetos paso a paso por un único bloque entre llaves.
¿Qué era el patrón Builder?
Recordemos brevemente el patrón Builder tradicional.
El patrón Builder crea un objeto complejo añadiendo sus componentes uno a uno, en lugar de construirlo todo de una vez.
let request = URLRequestBuilder()
.setURL("https://naver.com")
.setMethod("GET")
.addHeader("Accept", "application/json")
.build()
Lo ensamblamos encadenando métodos de esta forma.
Es fácil de leer, pero tiene inconvenientes. Hay que crear manualmente la clase Builder cada vez, y si olvidas build(), el objeto queda incompleto.
En otras palabras, el desarrollador debía gestionar directamente la lógica de ensamblaje.
resultBuilder delega precisamente esta parte al compilador.
¿Cómo funciona resultBuilder?
La idea central es sencilla.
El compilador introduce uno a uno los valores enumerados en un bloque entre llaves en funciones de reglas predefinidas y los combina en un único resultado final.
Esas funciones de reglas son métodos estáticos como buildBlock.
Por ejemplo, creemos un builder muy sencillo que recopile cadenas.
@resultBuilder
struct StringBuilder {
static func buildBlock(_ parts: String...) -> String {
parts.joined(separator: " ")
}
}
@StringBuilder
func greeting() -> String {
"Hola"
"resultBuilder"
"soy"
}
// Resultado: «Hola resultBuilder soy"
Dentro de la función greeting() solo enumeramos tres cadenas en tres líneas, ¿verdad?
El compilador sustituyó esas tres líneas por una llamada a buildBlock("안녕하세요", "resultBuilder", "입니다").
La sintaxis ha escrito por nosotros el código de ensamblaje que antes escribíamos a mano.
¿Cómo se procesan los condicionales y los bucles?
A veces queremos usar if o for dentro de un bloque, algo habitual también en SwiftUI.
Para eso, resultBuilder ofrece métodos de reglas adicionales.
Estos son los métodos principales, resumidos en una tabla.
| Método | ¿Cuándo se llama? |
|---|---|
buildBlock |
Al combinar varios valores del bloque en uno solo |
buildOptional |
Cuando solo existe if y no existe else |
buildEither(first:) / buildEither(second:) |
Al procesar la rama if-else |
buildArray |
Al recopilar los resultados repetidos de for |
buildExpression |
Al transformar primero la expresión de cada línea |
Los métodos que implementes determinan qué sintaxis permite el builder.
Si no creas buildOptional, no podrás usar if dentro del bloque.
Por eso el @ViewBuilder de SwiftUI implementa casi todos estos métodos. Gracias a ello, puedes usar condicionales y bucles con naturalidad dentro de los bloques de vistas.
Ventajas y precauciones tras usarlo
He usado resultBuilder para pequeños generadores de HTML y para construir datos de prueba.
Lo mejor fue que el sitio de llamada se vuelve declarativo y limpio. Como el proceso de ensamblaje queda oculto, el lector puede centrarse en «qué crear».
Aun así, hay precauciones claras.
- Los mensajes de error de compilación suelen ser poco útiles. Si los tipos no coinciden dentro de un bloque, el error puede señalar una ubicación completamente equivocada.
- Usarlo en exceso puede ser contraproducente. Si solo vas a crear un array sencillo, es mejor un literal de array.
- Al depurar, es difícil rastrear qué método
build...se llamó realmente.
Por eso recomiendo usarlo solo con estructuras que se ensamblan de forma repetida, como un DSL (Domain-Specific Language, lenguaje específico del dominio). SwiftUI, las definiciones de rutas del servidor y los query builders son buenos ejemplos.
Un consejo práctico para el desarrollo de iOS: normalmente es más importante entender y usar bien @ViewBuilder que crear @resultBuilder por tu cuenta.
Resumen
En resumen, resultBuilder es una evolución del patrón Builder que el lenguaje ha incorporado a partir del código que antes escribíamos manualmente.
Cuando entiendas que el compilador ensambla lo que enumeras entre llaves, comprenderás de forma natural por qué SwiftUI tiene ese diseño.
Escribe tú mismo el código del ejemplo de hoy. Se fija mucho más rápido que leyéndolo.

