Result Builder é um atributo do Swift implementado através do protocolo @resultBuilder que transforma uma sequência de expressões em um valor composto. O compilador converte blocos de código com construções de controle if, for, switch em chamadas a métodos estáticos do builder — buildBlock, buildEither, buildArray. De acordo com a proposta Swift Evolution SE-0289 (2022), os result builders permitem criar DSL declarativos dentro do Swift sem analisadores externos. O exemplo mais conhecido é o @ViewBuilder no SwiftUI, onde o corpo da view é construído a partir de elementos condicionais e cíclicos em um estilo declarativo.
Pontos principais
TupleViewif/else, switch, for-in através dos métodos buildOptional, buildEither, buildArrayResult Builder (anteriormente conhecido como function builders) é um mecanismo do Swift que permite transformar uma sequência de expressões separadas por quebras de linha em um único valor. Ele é declarado usando o atributo @resultBuilder aplicado a uma estrutura que implementa métodos estáticos de transformação.
Antes dos result builders, a sintaxe declarativa do body do SwiftUI era impossível. Em vez de uma lista compacta de views, os desenvolvedores teriam que escrever chamadas TupleView manualmente. O Result Builder envolve automaticamente cada expressão, suporta ramificações e loops, escondendo a complexidade da composição do desenvolvedor.
De acordo com Swift Evolution SE-0289, aceita em 2022, o result builder é uma evolução da ideia de function builders (SE-0258, Swift 5.1). Mudanças principais: renomear de @_functionBuilder para @resultBuilder e extensão para parâmetros de função, permitindo usar builders para qualquer argumento closure, não apenas para corpos de view.
Use result builders quando precisar fornecer aos usuários da sua biblioteca uma sintaxe declarativa para construir estruturas complexas — configurações, consultas, componentes de UI — sem escrever código de montagem imperativo.
O compilador Swift transforma cada bloco de código marcado com @resultBuilder em uma sequência de chamadas a métodos estáticos do builder. Vamos ver um builder simples que concatena strings:
@resultBuilder
struct StringBuilder {
static func buildBlock(_ parts: String...) -> String {
parts.joined(separator: " ")
}
}
Usando este builder — cada string em uma linha separada é concatenada com um espaço:
@StringBuilder
func greeting() -> String {
"Hello"
"World"
"from"
"Swift"
}
// O compilador transforma isso em:
// StringBuilder.buildBlock("Hello", "World", "from", "Swift")
// Resultado: "Hello World from Swift"
O compilador agrupa expressões consecutivas e as passa como parâmetros variádicos para buildBlock. Se um if aparece entre expressões, o compilador chama buildOptional ou buildEither para ramificação. Para loops for-in ele chama buildArray. Assim, o código Swift comum é transformado em uma cadeia de chamadas que constroem o valor final.
Cada result builder define um conjunto de métodos estáticos que o compilador chama durante a transformação. Os métodos principais:
| Método | Propósito | Quando é chamado |
|---|---|---|
| buildBlock | Combina uma sequência de expressões | Para cada bloco sem ramificação |
| buildOptional | Lida com if sem else | Quando há if sem else |
| buildEither(first:) | Primeiro ramo do if-else | Para if com else |
| buildEither(second:) | Segundo ramo do if-else | Para if com else |
| buildArray | Lida com loops for-in | Quando for-in está presente |
| buildExpression | Transforma expressões individuais | Para cada expressão antes de passar para buildBlock |
| buildFinalResult | Transformação final | Antes de retornar do closure |
Uma implementação mínima requer apenas buildBlock com parâmetros variádicos — isso é suficiente para blocos sem ramificação. Adicionar buildOptional e buildEither inclui suporte para construções condicionais, e buildArray para loops. De acordo com a Documentação Swift (2025), é recomendado implementar todos os métodos para máxima flexibilidade do DSL.
buildExpression permite aceitar expressões de diferentes tipos e convertê-las para um único tipo do builder. Por exemplo, no @ViewBuilder, buildExpression aceita Text, Image, Button e os converte para o tipo comum View.
Vamos considerar a criação de um builder para construir strings HTML. Este DSL permitirá escrever HTML declarativo diretamente em Swift:
@resultBuilder
enum HTMLBuilder {
static func buildBlock(_ components: String...) -> String {
components.joined()
}
static func buildOptional(_ component: String?) -> String {
component ?? ""
}
static func buildEither(first component: String) -> String {
component
}
static func buildEither(second component: String) -> String {
component
}
static func buildArray(_ components: [String]) -> String {
components.joined()
}
}
Usando o builder personalizado para gerar HTML:
func div(@HTMLBuilder _ content: () -> String) -> String {
"<div>\(content())</div>"
}
func p(_ text: String) -> String {
"<p>\(text)</p>"
}
let page = div {
p("Hello")
p("World")
if showFooter {
p("Rodapé")
}
}
// Resultado: <div><p>Hello</p><p>World</p><p>Footer</p></div>
De acordo com o artigo “Building Custom Result Builders in Swift” do Swift.org (2025), builders personalizados são usados em bibliotecas para construir arquivos de configuração, componentes de UI, mapeamento de dados e até consultas a banco de dados — em qualquer lugar onde uma sintaxe declarativa com suporte a ramificações seja necessária.
@ViewBuilder é um result builder integrado ao SwiftUI que é aplicado ao parâmetro content da maioria das views contêiner: VStack, HStack, ZStack, Group, List e a própria propriedade body. Ele permite escrever várias views em linhas separadas sem vírgulas ou encapsulamentos.
@ViewBuilder implementa todos os métodos do result builder, incluindo suporte para if-else, switch e for-in. Quando uma condição é verdadeira, buildEither(first:) retorna uma view; quando falsa, buildEither(second:) retorna outra. Ambos os ramos devem retornar o mesmo tipo, mas o SwiftUI usa AnyView internamente ou apagamento de tipo através de ConditionalContent.
struct GreetingView: View {
let isLoggedIn: Bool
var body: some View {
VStack {
Image(systemName: "person.circle")
Text("Perfil")
.font(.title)
if isLoggedIn {
Text("Bem-vindo de volta!")
.foregroundColor(.green)
} else {
Button("Entrar") { }
}
}
}
}
Sem @ViewBuilder, o mesmo código exigiria Group para cada seção condicional ou uso de AnyView, o que prejudica o desempenho. @ViewBuilder seleciona automaticamente a representação mais eficiente — ConditionalContent ou TupleView — para cada combinação.
A primeira limitação é o número máximo de expressões no buildBlock. A biblioteca padrão do Swift define sobrecargas de buildBlock para 2–10 expressões. Se um bloco tiver mais de 10 expressões, o compilador gerará um erro. A solução é agrupar através de Group ou VStack para dividir em sub-blocos.
A segunda limitação é a falta de suporte para variáveis e atribuições dentro do bloco do builder. Não é possível declarar let x = 5 dentro de @ViewBuilder. Todas as expressões devem ser expressões que retornam um valor do tipo do builder. Para cálculos intermediários, use cálculos fora do builder ou buildExpression com suporte para diferentes tipos.
A terceira limitação é a complexidade de depuração. Erros de compilação dentro de um result builder frequentemente produzem mensagens confusas, especialmente quando os tipos não correspondem nos ramos if/else. Use tipos de retorno explícitos e AnyView para depuração, embora este último reduza o desempenho. De acordo com Hacking with Swift (2025), uma dica prática é começar com um builder simples sem ramificações e adicionar suporte para construções condicionais gradualmente.
Perguntas frequentes
Result Builder é um atributo Swift que transforma uma sequência de expressões em um valor resultante através de métodos estáticos. Permite criar DSL declarativos, o exemplo mais conhecido é @ViewBuilder no SwiftUI para construir hierarquias de view sem código imperativo.
Declare uma estrutura com o atributo @resultBuilder e implemente pelo menos o método buildBlock. Para suportar condições, adicione buildOptional e buildEither; para loops, adicione buildArray. Use o atributo do builder antes do parâmetro closure em uma função.
Apenas buildBlock é obrigatório. Todos os outros métodos — buildOptional, buildEither, buildArray, buildExpression, buildFinalResult — são opcionais e adicionam suporte para as construções correspondentes. Quanto mais métodos implementados, mais flexível o DSL.
@ViewBuilder é uma implementação concreta do result builder para o protocolo View. Ele é definido no SwiftUI como uma estrutura com o atributo @resultBuilder, fornecendo métodos buildBlock para diferentes quantidades de views (TupleView), buildEither para ConditionalContent e buildArray para ForEach.
Sim, as sobrecargas padrão do buildBlock suportam até 10 expressões. Ao exceder isso, use contêineres aninhados (Group, VStack) para dividir em sub-blocos. Um builder personalizado pode definir um buildBlock variádico sem limitação.
Resumo
buildBlock, buildEither, buildOptional, buildArray dependendo das construções de controleVamos desenvolver um aplicativo móvel chave na mão
A IT Sectr cria aplicativos para iOS e Android para startups e empresas desde 2017. Nós vamos aconselhá-lo e propor a melhor solução.
Leia também