@Environment di SwiftUI — property wrapper untuk membaca nilai dari lingkungan sistem, yang secara otomatis disebarkan melalui hierarki View. Komponen ini menyediakan akses ke skema warna, locale, ukuran fon, managedObjectContext, dan puluhan parameter sistem lainnya. Menurut Apple Developer Documentation (2025), @Environment menjamin bahwa setiap perubahan nilai lingkungan akan memicu penggambaran ulang semua View yang berlangganan, memastikan pembaruan antarmuka yang reaktif tanpa panggilan manual.
Hal Penting
@Environment — adalah property wrapper SwiftUI yang dirancang untuk membaca nilai dari lingkungan sistem. Lingkungan adalah wadah hierarkis nilai yang secara otomatis disebarkan SwiftUI dari View induk ke View anak. Setiap nilai lingkungan diidentifikasi oleh kunci — tipe yang sesuai dengan protokol EnvironmentKey.
Mekanisme lingkungan menyerupai dependency injection di tingkat framework: sistem menyediakan serangkaian nilai yang telah ditentukan — skema warna (terang/gelap), locale, ukuran fon, managedObjectContext untuk Core Data, dismiss untuk menutup layar, dan banyak lainnya. View yang mendeklarasikan @Environment dengan kunci tertentu secara otomatis menerima nilai saat ini dan digambar ulang saat nilainya berubah.
Arsitektur lingkungan SwiftUI didasarkan pada protokol EnvironmentValues — struktur yang berisi semua nilai sistem. Setiap nilai disimpan sebagai properti dari struktur ini dengan getter dan setter. @Environment menggunakan key path untuk mengakses properti tertentu: @Environment(\.colorScheme) — akses ke skema warna, @Environment(\.locale) — ke locale.
Property wrapper @Environment mengimplementasikan dua mekanisme kunci: membaca nilai dari lingkungan dan berlangganan perubahannya. Saat membuat View, SwiftUI menelusuri semua properti @Environment dan mengikatnya ke nilai yang sesuai dari konteks saat ini. Jika View induk mengubah nilai melalui modifier .environment(), semua View anak yang membaca nilai ini akan digambar ulang secara otomatis.
Fitur penting: @Environment mendukung nilai opsional. Jika nilai tidak ditetapkan dalam hierarki, nilai default yang didefinisikan di EnvironmentKey akan dikembalikan. Untuk kunci sistem, nilai default selalu masuk akal — misalnya, skema warna default .light. Untuk kunci kustom, pengembang sendiri yang menentukan nilai default dalam metode defaultValue protokol EnvironmentKey.
struct EnvironmentReaderView: View {
@Environment(\.colorScheme) var colorScheme
@Environment(\.locale) var locale
@Environment(\.sizeCategory) var sizeCategory
var body: some View {
VStack {
Text("Skema saat ini: \(colorScheme == .dark ? "Dark" : "Light")")
Text("Locale: \(locale.identifier)")
Text("Ukuran fon: \(sizeCategory)")
}
}
}
Dalam contoh, View membaca tiga nilai lingkungan sistem. Saat colorScheme berubah — misalnya, pengguna mengaktifkan mode gelap di pengaturan — View secara otomatis digambar ulang dengan nilai baru. Demikian pula saat wilayah atau ukuran fon (Dynamic Type) berubah. View tidak perlu berlangganan pemberitahuan atau memanggil penyegaran — SwiftUI mengelola ini secara otomatis.
SwiftUI menyediakan puluhan nilai lingkungan sistem yang mencakup berbagai aspek antarmuka dan perilaku. Skema warna (\.colorScheme) — salah satu nilai yang paling banyak diminta, memungkinkan penyesuaian antarmuka dengan tema terang dan gelap. Locale (\.locale) berisi pengaturan regional pengguna untuk memformat tanggal, angka, dan mata uang.
Untuk Core Data, digunakan managedObjectContext (\.managedObjectContext) — konteks yang diteruskan melalui lingkungan dari persistence container. Untuk navigasi, tersedia dismiss (\.dismiss) untuk menutup layar saat ini dan isPresented (\.isPresented) untuk tampilan modal. Untuk kalender dan zona waktu — masing-masing calendar dan timeZone.
| Key Path | Tipe | Tujuan |
|---|---|---|
| \.colorScheme | ColorScheme | Tema terang atau gelap |
| \.locale | Locale | Pengaturan regional |
| \.sizeCategory | ContentSizeCategory | Ukuran fon Dynamic Type |
| \.managedObjectContext | NSManagedObjectContext | Konteks Core Data |
| \.dismiss | DismissAction | Menutup layar |
| \.calendar | Calendar | Kalender saat ini |
| \.timeZone | TimeZone | Zona waktu |
| \.horizontalSizeClass | UserInterfaceSizeClass | Ukuran horizontal layar |
Untuk mengakses nilai sistem, gunakan key path melalui titik: @Environment(\.dismiss) var dismiss. Kompiler memeriksa keberadaan key path di EnvironmentValues, jadi kunci yang salah akan menyebabkan kesalahan pada tahap kompilasi. Nilai sistem baru ditambahkan oleh Apple dengan setiap versi iOS — daftar saat ini tersedia di dokumentasi EnvironmentValues.
Meskipun namanya mirip, @Environment dan @EnvironmentObject menyelesaikan tugas yang berbeda. @Environment membaca nilai sistem atau kustom yang terdaftar melalui EnvironmentKey. @EnvironmentObject — adalah property wrapper untuk ObservableObject, yang diteruskan melalui lingkungan berdasarkan tipe, tanpa kunci eksplisit.
@EnvironmentObject digunakan untuk dependency injection: View induk membuat objek (misalnya, ViewModel) dan meneruskannya ke View anak melalui modifier .environmentObject(). View anak menerimanya melalui @EnvironmentObject dan dapat membaca serta mengubah propertinya. @Environment — hanya baca untuk nilai sistem dan tidak mendukung umpan balik.
| Parameter | @Environment | @EnvironmentObject |
|---|---|---|
| Tujuan | Nilai sistem dan kustom | Injeksi ObservableObject |
| Kunci | Key path EnvironmentValues | Berdasarkan tipe objek |
| Tulis | Hanya baca | Baca dan tulis |
| Nilai kustom | Melalui EnvironmentKey | Melalui kelas ObservableObject |
| Nilai default | Ada (defaultValue) | Tidak ada (harus diteruskan) |
Dalam praktiknya: gunakan @Environment untuk mengakses parameter sistem (tema, locale, ukuran fon) dan konfigurasi kustom yang tidak berubah saat runtime. Gunakan @EnvironmentObject untuk meneruskan ViewModel atau layanan melalui hierarki View ketika status perlu diubah dari komponen anak.
Mari kita lihat pembuatan nilai lingkungan kustom. Untuk ini, Anda perlu mendefinisikan struktur yang sesuai dengan protokol EnvironmentKey dan memperluas EnvironmentValues dengan properti baru. Ini memungkinkan penerusan konfigurasi tema atau pengaturan aplikasi melalui seluruh pohon View tanpa props.
struct AppThemeKey: EnvironmentKey {
static let defaultValue: AppTheme = .system
}
extension EnvironmentValues {
var appTheme: AppTheme {
get { self[AppThemeKey.self] }
set { self[AppThemeKey.self] = newValue }
}
}
enum AppTheme { case system, light, dark }
Protokol EnvironmentKey memerlukan implementasi properti statis defaultValue — nilai yang akan digunakan jika View induk belum menetapkan lingkungan kustom. Ekstensi EnvironmentValues menambahkan properti terhitung appTheme, menggunakan subscript dengan kunci. Setelah itu, View mana pun dapat membaca nilai melalui @Environment(\.appTheme).
struct ThemedView: View {
@Environment(\.appTheme) var appTheme
@Environment(\.colorScheme) var colorScheme
var body: some View {
VStack {
if appTheme == .dark || (appTheme == .system && colorScheme == .dark) {
Text("Mode gelap aktif")
.foregroundStyle(.white)
.background(Color.black)
} else {
Text("Mode terang aktif")
.foregroundStyle(.black)
.background(Color.white)
}
}
}
}
struct ContentView: View {
@State private var selectedTheme = AppTheme.system
var body: some View {
ThemedView()
.environment(\.appTheme, selectedTheme)
}
}
ThemedView membaca dua lingkungan: appTheme kustom dan colorScheme sistem. Kombinasi ini memungkinkan implementasi pengaturan tema yang fleksibel: pengguna dapat memilih tema “Terang”, “Gelap”, atau “Sistem”. Jika sistem dipilih — nilai diambil dari colorScheme, yang secara otomatis berubah saat tema diganti di pengaturan iOS. View induk (ContentView) menetapkan nilai appTheme melalui modifier .environment().
struct ModalView: View {
@Environment(\.dismiss) var dismiss
@State private var name = ""
var body: some View {
NavigationStack {
Form {
TextField("Your name", text: $name)
Button("Simpan") { dismiss() }
}
.navigationTitle("Edit Profile")
}
}
}
Contoh ini mendemonstrasikan penggunaan praktis dismiss — instance DismissAction dari lingkungan. Pemanggilan dismiss() sebagai fungsi menutup layar modal atau mengembalikan NavigationLink. Satu-satunya persyaratan — View harus ditampilkan secara modal atau berada di dalam NavigationStack. dismiss ditentukan secara otomatis dari konteks: jika View dibuka sebagai sheet — sheet ditutup, jika sebagai popover — popover ditutup.
Pertanyaan Umum
Tidak, @Environment dirancang hanya untuk baca. Untuk mengubah nilai, gunakan @EnvironmentObject dengan ObservableObject atau @Binding. EnvironmentKey kustom dapat memiliki setter di ekstensi, tetapi perubahan melalui setter tersebut tidak memicu pembaruan UI — ini secara teknis mungkin, tetapi tidak disarankan.
@Binding menciptakan koneksi dua arah dengan sumber kebenaran (State, StateObject, ObservableObject). @Environment — pembacaan satu arah dari konteks hierarkis. @Binding cocok untuk meneruskan data ke View anak, @Environment — untuk akses ke pengaturan sistem atau global.
Definisikan struktur yang mengimplementasikan protokol EnvironmentKey dengan static defaultValue. Kemudian perluas EnvironmentValues dengan properti yang memiliki getter/setter melalui subscript[key]. Setelah registrasi, gunakan @Environment(\.yourKey) untuk membaca dan .environment(\.yourKey, value) untuk menetapkan.
SwiftUI menyediakan lebih dari 50 nilai sistem: colorScheme, locale, sizeCategory, managedObjectContext, dismiss, calendar, timeZone, horizontalSizeClass, verticalSizeClass, accessibilityEnabled, layoutDirection, legibilityWeight dan lainnya. Daftar lengkap di dokumentasi EnvironmentValues.
Ya, @Environment berfungsi di Preview, tetapi nilai default mungkin berbeda dari simulator. Untuk pengujian di Preview, gunakan modifier .environment() langsung di kode Preview: ThemedView().environment(\.colorScheme, .dark). Ini memungkinkan pemeriksaan visual berbagai keadaan lingkungan.
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