@ViewBuilder — adalah anotasi result builder di SwiftUI, yang dirancang untuk pembangunan hierarki View secara deklaratif. Menurut Apple Developer Documentation, 2024, @ViewBuilder mengubah blok kode dengan banyak ekspresi dan logika kondisional menjadi satu tipe View yang dapat dipahami oleh kompiler Swift. Tanpa anotasi ini, tidak mungkin menggunakan sintaksis deklaratif SwiftUI yang familiar dengan if/else dan beberapa elemen di body.
Poin Penting
@ViewBuilder — adalah anotasi yang mengimplementasikan pola result builder (SE-0289), yang memungkinkan SwiftUI mengumpulkan beberapa View menjadi satu komposisi menggunakan sintaksis deklaratif. Anotasi ini secara otomatis membungkus banyak ekspresi, konstruksi kondisional, dan nilai opsional ke dalam tipe yang sesuai: TupleView, ConditionalContent, OptionalContent.
Sebelum munculnya result builder, pengembang harus membungkus elemen secara manual ke dalam VStack atau HStack, dan untuk logika kondisional menggunakan operator ternary atau metode pabrik. @ViewBuilder membuat sintaksis SwiftUI menjadi ringkas dan mudah dibaca, memungkinkan penulisan kode yang terlihat seperti Swift biasa dengan if/else dan perulangan.
Menurut Swift Evolution SE-0289, result builders adalah mekanisme umum yang tidak terikat pada SwiftUI. @ViewBuilder adalah salah satu implementasi dari mekanisme ini, bersama dengan @StringBuilder untuk membangun string dan implementasi perpustakaan untuk DSL lainnya. Di SwiftUI, @ViewBuilder digunakan tidak hanya untuk body, tetapi juga untuk parameter penutup wadah (VStack, HStack, ZStack, List).
Di UIKit imperatif, Anda secara imperatif membuat UIView, mengonfigurasi propertinya, dan menambahkannya ke hierarki melalui addSubview. Di SwiftUI dengan @ViewBuilder, Anda secara deklaratif mendeskripsikan View mana yang akan ditampilkan, dan SwiftUI sendiri mengelola pembuatan, pembaruan, dan penghapusan elemen berdasarkan perubahan status.
Result builder — adalah mekanisme Swift yang mengubah urutan ekspresi menjadi satu nilai gabungan melalui metode statis buildBlock, buildOptional, buildEither dan lainnya. Ketika kompiler melihat anotasi @ViewBuilder, ia secara otomatis menerapkan metode ini ke blok kode selama proses kompilasi.
@resultBuilder
struct ViewBuilder {
static func buildBlock<C0, C1>(_ c0: C0, _ c1: C1) -> TupleView<(C0, C1)>
static func buildIf<C>(_ c: C?) -> C?
static func buildEither<T, F>(first: T) -> ConditionalContent<T, F>
static func buildEither<T, F>(second: F) -> ConditionalContent<T, F>
}
buildBlock menerima 1 hingga 10 ekspresi dan mengembalikan TupleView. Setiap aritas (jumlah ekspresi) memiliki overload buildBlock sendiri: dari buildBlock<C0> hingga buildBlock<C0, C1, ..., C9>. Itulah sebabnya jumlah elemen dalam satu blok @ViewBuilder dibatasi hingga 10.
buildEither (first/second) memproses konstruksi if/else. Setiap cabang diteruskan ke metode yang sesuai, dan hasilnya dibungkus dalam ConditionalContent — tipe yang menyembunyikan tipe spesifik cabang dan menyediakan antarmuka terpadu untuk SwiftUI.
Di SwiftUI, properti body sudah secara implisit dianotasi dengan @ViewBuilder — Anda tidak melihat anotasi ini dalam kode, tetapi kompiler menerapkannya secara otomatis. Namun, untuk properti pengguna yang mengembalikan beberapa View atau untuk parameter penutup, anotasi harus ditentukan secara eksplisit.
Batasan 1 — 10 elemen dalam satu blok. Ini adalah batasan paling terkenal dari @ViewBuilder. Jika perlu menampilkan lebih dari 10 elemen pada satu tingkat, kompiler akan memberikan kesalahan. Anda dapat mengatasinya dengan Group, ForEach, List atau pemisahan menjadi subkomponen. Group tidak menambahkan penyarangan visual, tetapi setiap Group dihitung sebagai satu elemen.
struct ManyElementsView: View {
var body: some View {
Group {
Text("1"); Text("2"); Text("3")
Text("4"); Text("5"); Text("6")
Text("7"); Text("8"); Text("9")
}
Group {
Text("10"); Text("11"); Text("12")
}
}
}
Batasan 2 — kurangnya dukungan untuk beberapa konstruksi. @ViewBuilder tidak mendukung do/catch, guard, for-in (tanpa ForEach) dan konstruksi kontrol lainnya. Untuk perulangan, gunakan ForEach dengan data yang dapat diidentifikasi. Untuk penanganan kesalahan, gunakan View terpisah yang menerima Result atau nilai opsional.
Batasan 3 — kesulitan debugging. Pada kesalahan di @ViewBuilder, kompiler menghasilkan pesan verbose yang sulit menemukan akar penyebabnya. Masalah umum: ketidakcocokan tipe di cabang if/else, melebihi batas 10 elemen, atau tidak adanya overload buildBlock yang diperlukan.
Pola 1: tampilan bersyarat melalui if/else. Skenario penggunaan paling umum dari @ViewBuilder. Memungkinkan menampilkan View yang berbeda tergantung pada status tanpa menggunakan operator ternary atau metode pabrik.
struct StatusView: View {
var status: LoadStatus
@ViewBuilder
var body: some View {
switch status {
case .loading:
ProgressView("Loading...")
case .loaded(let data):
DataView(data: data)
case .error(let message):
ErrorView(message: message)
}
}
}
Pola 2: @ViewBuilder dalam parameter fungsi dan inisialisasi. Digunakan untuk membuat wadah yang dapat digunakan kembali yang menerima View anak melalui penutup. Ini adalah pola standar untuk perpustakaan dan komponen UI.
struct SectionCard<Content: View>: View {
let title: String
@ViewBuilder let content: Content
var body: some View {
VStack(alignment: .leading) {
Text(title).font(.headline)
content
}
.padding()
.background(Color.gray.opacity(0.1))
.cornerRadius(12)
}
}
Pola 3: komposisi dengan ForEach. @ViewBuilder bekerja dengan benar dengan ForEach, memungkinkan pembuatan elemen secara dinamis dari array data. Setiap elemen ForEach dihitung sebagai satu ekspresi dalam konteks @ViewBuilder.
ViewBuilder kustom — adalah fungsi atau properti pengguna yang dianotasi dengan @ViewBuilder yang mengembalikan some View. Fungsi semacam itu memungkinkan enkapsulasi logika tampilan yang kompleks dan penggunaannya kembali di berbagai bagian aplikasi.
struct FormRow<Content: View>: View {
let label: String
@ViewBuilder let content: Content
var body: some View {
HStack {
Text(label)
.frame(width: 120, alignment: .trailing)
content
}
}
}
// Penggunaan:
FormRow(label: "Name") {
TextField("Enter name", text: $name)
}
FormRow(label: "Gender") {
Picker("Select", selection: $gender) {
Text("Pria").tag(Gender.male)
Text("Wanita").tag(Gender.female)
}
}
Aturan penting: fungsi kustom dengan @ViewBuilder harus mengembalikan some View, bukan tipe spesifik atau protokol View. Hanya tipe opaque yang memungkinkan penyembunyian implementasi spesifik dan menjaga fleksibilitas komposisi.
Kinerja: fungsi @ViewBuilder kustom tidak menambah overhead dibandingkan dengan kode langsung di body. Kompiler melakukan inline pada panggilan dan mengoptimalkan kode yang dihasilkan. Memisahkan body menjadi fungsi @ViewBuilder meningkatkan keterbacaan tanpa kehilangan kinerja.
Pertanyaan yang Sering Diajukan
@ViewBuilder — adalah anotasi result builder yang mengubah blok kode dengan banyak ekspresi dan kondisi menjadi satu tipe View. Ini memungkinkan penggunaan sintaksis Swift yang familiar (if/else, switch, ekspresi opsional) di dalam UI deklaratif SwiftUI.
Batasan terkait dengan implementasi buildBlock — untuk setiap aritas dari 1 hingga 10 ada overload terpisah dari metode ini. Swift tidak mendukung variadic generics, sehingga jumlah overload tetap. Untuk mengatasinya, gunakan Group, ForEach atau subkomponen.
Tidak, protokol View secara implisit menerapkan @ViewBuilder ke properti body. Namun, untuk properti pengguna, metode, dan parameter penutup yang mengembalikan beberapa View, anotasi harus ditentukan secara eksplisit. Tanpa itu, kompiler tidak akan dapat memproses banyak ekspresi.
Untuk ekspresi opsional digunakan metode buildIf, yang menerima View opsional dan mengembalikannya jika nilainya ada. Jika nilainya nil — buildIf mengembalikan nil dan elemen tidak ditampilkan. Ini memungkinkan penggunaan if let di body.
Ya, sejak Swift 5.9 @ViewBuilder mendukung switch melalui metode buildExpression. Kompiler mengubah setiap cabang case menjadi panggilan buildEither yang sesuai. Dukungan switch membuat kode lebih mudah dibaca dibandingkan dengan konstruksi if/else bersarang.
Ringkasan
Kami akan mengembangkan aplikasi seluler turnkey
IT Sectr membuat aplikasi iOS dan Android untuk startup dan bisnis sejak 2017. Kami akan memberi saran dan mengusulkan solusi terbaik.
Baca juga