@Environment ใน SwiftUI — คืออะไร แนวคิดสำคัญ และกลไก

ผู้แต่ง: IT Sectr เผยแพร่เมื่อ: 2026-06-25 เวลาอ่าน: 8 นาที

@Environment ใน SwiftUI เป็น property wrapper สำหรับอ่านค่าจากสภาพแวดล้อมของระบบ ซึ่งแจกจัดโดยอัตโนมัติผ่านลำดับชั้น View ส่วนประกอบนี้ให้การเข้าถึงโครงสี ตำแหน่งที่อยู่ ขนาดแบบอักษร managedObjectContext และพารามิเตอร์ระบบอื่นๆ อีกมากมาย ตาม เอกสาร Apple Developer (2025), @Environment รับประกันว่าการเปลี่ยนแปลงค่าสภาพแวดล้อมใดๆ จะทำให้เกิดการเรียกโหมาระบายใหม่ของ View ทั้งหมดที่สมัครสมาชิก ซึ่งให้การอัพเดตอินเตอร์เฟสแบบรีแอคทีฟโดยไม่ต้องเรียกด้วยตนเอง

ประเด็นสำคัญ

  • @Environment — property wrapper สำหรับอ่านค่าสภาพแวดล้อมของระบบ SwiftUI
  • โครงสี ตำแหน่งที่อยู่ และขนาดแบบอักษรเป็นค่าระบบที่ใช้ทั่วไป
  • การเปลี่ยนแปลง ค่าสภาพแวดล้อมใดๆ จะทำให้เกิดการเรียกโหมาระบายใหม่โดยอัตโนมัติของ View ที่สมัครสมาชิก
  • คีย์ที่กำหนดเอง ช่วยให้สร้างค่าสภาพแวดล้อมของตนเองผ่าน EnvironmentKey
  • @Environment — สำหรับอ่านอย่างเดียว; @EnvironmentObject — สำหรับการเขียน

@Environment ใน SwiftUI คืออะไร?

@Environment เป็น SwiftUI property wrapper ที่ออกแบบมาสำหรับอ่านค่าจากสภาพแวดล้อมของระบบ สภาพแวดล้อมเป็นตัวเก็บค่าแบบลำดับชั้นที่ SwiftUI แจกจัดโดยอัตโนมัติจาก View แม่ไปยัง View ลูก แต่ละค่าสภาพแวดล้อมจะถูกระบุโดยคีย์ — ชนิดที่ปฏิบัติตามโปรโตคอล EnvironmentKey

กลไกของสภาพแวดล้อมมีลักษณะคล้ายกับ dependency injection ในระดับ framework: ระบบจัดหาชุดค่าที่กำหนดไว้ล่วงหน้า — โครงสี (สว่าง/มืด), ตำแหน่งที่อยู่, ขนาดแบบอักษร, managedObjectContext สำหรับ Core Data, dismiss สำหรับปิดหน้าจอ, และอื่นๆ อีกมากมาย View ที่ประกาศ @Environment ด้วยคีย์เฉพาะจะได้รับค่าปัจจุบันโดยอัตโนมัติ และจะถูกเรียกโหมาระบายใหม่เมื่อมันเปลี่ยนแปลง

สถาปัตยกรรมสภาพแวดล้อม SwiftUI อาศยโปรโตคอล EnvironmentValues — โครงสร้างที่ประกอบด้วยค่าระบบทั้งหมด แต่ละค่าจะถูกเก็บไว้เป็นคุณสมบัติของโครงสร้างนี้ที่มี getter และ setter @Environment ใช้ key path เพื่อเข้าถึงคุณสมบัติเฉพาะ: @Environment(\.colorScheme) — เข้าถึงโครงสี, @Environment(\.locale) — เข้าถึงตำแหน่งที่อยู่

@Environment ในฐานะ Property Wrapper

Property wrapper @Environment ใช้กลไกสำคัญสองอย่าง: การอ่านค่าจากสภาพแวดล้อม และการสมัครสมาชิกกับการเปลี่ยนแปลงของมัน เมื่อมีการสร้าง View, SwiftUI จะผ่านคุณสมบัติ @Environment ทั้งหมด และเชื่อมโยงมันกับค่าที่สอดคล้องกับบริบท์ปัจจุบัน หาก View แม่เปลี่ยนแปลงค่าโดยใช้ตัวแก้ไข .environment() View ลูกทั้งหมดที่อ่านค่านั้นจะถูกเรียกโหมาระบายใหม่โดยอัตโนมัติ

คุณสมบัติที่สำคัญ: @Environment รองรับค่าตัวเลือกได้ หากไม่มีการตั้งค่าในลำดับชั้น ระบบจะส่งค่าเริ่มต้นที่กำหนดไว้ใน EnvironmentKey กลับคืน สำหรับคีย์ระบบ ค่าเริ่มต้นจะมีความสมเหตุสมผลเสมอ — ตัวอย่างเช่น, โครงสีเริ่มต้นคือ .light สำหรับ คีย์ที่กำหนดเอง นักพัฒนาจะเป็นผู้กำหนดค่าเริ่มต้นในเมธอด defaultValue ของโปรโตคอล EnvironmentKey

swift
struct EnvironmentReaderView: View {
    @Environment(\.colorScheme) var colorScheme
    @Environment(\.locale) var locale
    @Environment(\.sizeCategory) var sizeCategory

    var body: some View {
        VStack {
            Text("Current scheme: \(colorScheme == .dark ? "Dark" : "Light")")
            Text("Locale: \(locale.identifier)")
            Text("Font size: \(sizeCategory)")
        }
    }
}

ในตัวอย่าง View อ่านค่าสภาพแวดล้อมของระบบสามค่า เมื่อ colorScheme เปลี่ยนแปลง — ตัวอย่างเช่น, ผู้ใช้เปิดใช้โหมดมืดในการตั้งค่า — View จะถูกเรียกโหมาระบายใหม่โดยอัตโนมัติด้วยค่าใหม่ เช่นเดียวกันเมื่อภูมิภาคหรือขนาดแบบอักษร (Dynamic Type) เปลี่ยนแปลง View ไม่จำเป็นต้องสมัครสมาชิกกับการแจ้งเตือนหรือเรียก refresh — SwiftUI จัดการเรื่องนี้โดยอัตโนมัติ

ค่าสภาพแวดล้อมของระบบ

SwiftUI มีค่าสภาพแวดล้อมของระบบมากมายที่ครอบคลุมด้านต่างๆ ของส่วนติดต่อผู้ใช้และพฤติกรรม โครงสี (\.colorScheme) เป็นหนึ่งในค่าที่ใช้กันบ่อยที่สุด, ช่วยให้ส่วนติดต่อผู้ใช้ปรับตัวตามโครงสีสว่างและมืด ตำแหน่งที่อยู่ (\.locale) ประกอบด้วยการตั้งค่าภูมิภาคของผู้ใช้สำหรับการจัดรูปแบบวันที่, ตัวเลข และสกุลเงิน

สำหรับ Core Data, ใช้ managedObjectContext (\.managedObjectContext) — บริบท์ที่ส่งต่อผ่านสภาพแวดล้อมจากคอนเทนเนอร์การจัดเก็บข้อมูล สำหรับการนำทาง, มี dismiss (\.dismiss) สำหรับปิดหน้าจอปัจจุบัน และ isPresented (\.isPresented) สำหรับการนำเสนอแบบ modal สำหรัปปฏิทินและโซนเวลา — calendar และ timeZone ตามลำดับ

Key Pathชนิดวัตถุประสงค์
\.colorSchemeColorSchemeโครงสีสว่างหรือมืด
\.localeLocaleการตั้งค่าภูมิภาค
\.sizeCategoryContentSizeCategoryขนาดแบบอักษร Dynamic Type
\.managedObjectContextNSManagedObjectContextบริบท์ Core Data
\.dismissDismissActionปิดหน้าจอ
\.calendarCalendarปฏิทินปัจจุบัน
\.timeZoneTimeZoneโซนเวลา
\.horizontalSizeClassUserInterfaceSizeClassขนาดหน้าจอแนวนอน

เพื่อเข้าถึงค่าระบบ, ใช้ key path ที่มีจุด: @Environment(\.dismiss) var dismiss ตัวคอมไพเลอร์จะตรวจสอบการมีอยู่ของ key path ใน EnvironmentValues, ดังนั้นคีย์ที่ไม่ถูกต้องจะทำให้เกิดข้อผิดพลาดขณะคอมไพล์ Apple เพิ่มค่าระบบใหม่ๆ ในทุกรุ่น iOS — รายชื่อที่ครบถ้วนมีอยู่ในเอกสาร EnvironmentValues

@Environment vs @EnvironmentObject

แม้ว่าจะมีชื่อคล้ายกัน แต่ @Environment และ @EnvironmentObject ทำงานคนละวัตถุประสงค์ที่แตกต่างกัน @Environment อ่านค่าระบบหรือค่าที่กำหนดเองที่ลงทะเบียนผ่าน EnvironmentKey @EnvironmentObject เป็น property wrapper สำหรับ ObservableObject ที่ส่งต่อผ่านสภาพแวดล้อมตามชนิด, โดยไม่มีคีย์ที่ชัดเจน

@EnvironmentObject ใช้สำหรับ dependency injection: View แม่สร้างอ็อบเจ็กต์ (เช่น ViewModel) และส่งต่อไปยัง View ลูกโดยใช้ตัวแก้ไข .environmentObject() View ลูกจะได้รับมันผ่าน @EnvironmentObject และสามารถอ่านและแก้ไขคุณสมบัติของมัน ในทางกลับกัน, @Environment เป็นแบบ อ่านอย่างเดียว สำหรับค่าระบบ และไม่รองรับการติชมกลับ

พารามิเตอร์@Environment@EnvironmentObject
วัตถุประสงค์ค่าระบบและค่าที่กำหนดเองการฉีด ObservableObject
คีย์Key path ของ EnvironmentValuesตามชนิดของอ็อบเจ็กต์
การเขียนอ่านอย่างเดียวอ่านและเขียน
ค่าที่กำหนดเองผ่าน EnvironmentKeyผ่านคลาส ObservableObject
ค่าเริ่มต้นมี (defaultValue)ไม่มี (ต้องส่งต่อ)

ในทางปฏิบัติ: ใช้ @Environment สำหรับเข้าถึงพารามิเตอร์ระบบ (โครงสี, ตำแหน่งที่อยู่, ขนาดแบบอักษร) และการกำหนดค่าที่กำหนดเองที่ไม่เปลี่ยนแปลงในระะเวลาทำงาน ใช้ @EnvironmentObject สำหรับการส่งต่อ ViewModel หรือบริการผ่านลำดับชั้น View เมื่อจำเป็นต้องแก้ไขสถานะจากคอมโพนอนต์ย่อย

ตัวอย่างโค้ด @Environment

มาดูการสร้างค่าสภาพแวดล้อมที่กำหนดเอง สำหรับเรื่องนี้, คุณต้องกำหนดโครงสร้างที่ตรงตามโปรโตคอล EnvironmentKey และขยาย EnvironmentValues ด้วยคุณสมบัติใหม่ วิธีนี้ทำให้สามารถส่งการกำหนดค่าโครงสีหรือการตั้งค่าแอปผ่านต้นไม้ View ทั้งหมดโดยไม่ต้องใช้ props

swift
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 }

โปรโตคอล EnvironmentKey ต้องการให้ใช้คุณสมบัติสถิต defaultValue — ค่าที่จะใช้หาก View แม่ไม่ได้ตั้งค่าสภาพแวดล้อมที่กำหนดเอง การขยาย EnvironmentValues จะเพิ่มคุณสมบัติแบบคำนวณ appTheme โดยใช้ subscript กับคีย์ หลังจากนั้น, View ใดๆ ก็สามารถอ่านค่าผ่าน @Environment(\.appTheme)

การใช้ @Environment กับคีย์ที่กำหนดเอง

swift
struct ThemedView: View {
    @Environment(\.appTheme) var appTheme
    @Environment(\.colorScheme) var colorScheme

    var body: some View {
        VStack {
            if appTheme == .dark || (appTheme == .system && colorScheme == .dark) {
                Text("Dark mode active")
                    .foregroundStyle(.white)
                    .background(Color.black)
            } else {
                Text("Light mode active")
                    .foregroundStyle(.black)
                    .background(Color.white)
            }
        }
    }
}

struct ContentView: View {
    @State private var selectedTheme = AppTheme.system

    var body: some View {
        ThemedView()
            .environment(\.appTheme, selectedTheme)
    }
}

ThemedView อ่านสองสภาพแวดล้อม: appTheme ที่กำหนดเอง และ colorScheme ของระบบ การรวมกันช่วยให้สามารถกำหนดค่าโครงสีได้อย่างยืดหยุ่น: ผู้ใช้สามารถเลือกโครงสีสว่าง, มืด หรือตามระบบ หากเลือกตามระบบ, ค่าจะถูกนำจาก colorScheme ซึ่งเปลี่ยนแปลงโดยอัตโนมัติเมื่อสลับโครงสีในการตั้งค่า iOS View แม่ (ContentView) ตั้งค่า appTheme โดยใช้ตัวแก้ไข .environment()

การใช้ dismiss เพื่อปิดหน้าจอ

swift
struct ModalView: View {
    @Environment(\.dismiss) var dismiss
    @State private var name = ""

    var body: some View {
        NavigationStack {
            Form {
                TextField("Your name", text: $name)
                Button("Save") { dismiss() }
            }
            .navigationTitle("Edit Profile")
        }
    }
}

ตัวอย่างนี้แสดงการใช้งานจริงของ dismiss — อินสแตนซ์ของ DismissAction จากสภาพแวดล้อม การเรียก dismiss() เป็นฟังก์ชันจะปิดหน้าจอ modal หรือกลับ NavigationLink ข้อกำหนดเดียวคือ View ต้องถูกนำเสนอแบบ modal หรืออยู่ภายใน NavigationStack dismiss จะถูกกำหนดโดยอัตโนมัติจากบริบท์: หาก View ถูกเปิดเป็น sheet — sheet จะปิด, หากเป็น popover — popover จะปิด

คำถามที่พบบ่อย

ฉันสามารถเปลี่ยนค่า @Environment จาก View ลูกได้หรือไม่?

ไม่ได้, @Environment เป็นแบบอ่านอย่างเดียว สำหรับเปลี่ยนค่า, ใช้ @EnvironmentObject กับ ObservableObject หรือ @Binding คุณสมบัติของ EnvironmentKey ที่กำหนดเองสามารถมี setter ในส่วนขยายได้ แต่การเปลี่ยนผ่านมันจะไม่ทริเกอร์การอัพเดต UI — เป็นไปได้ทางเทคนิคแต่ไม่แนะนำ

@Environment แตกต่างจาก @Binding อย่างไร?

@Binding สร้างการเชื่อมต่อแบบสองทางกับแหล่งความจริง (State, StateObject, ObservableObject) @Environment เป็นการอ่านทางเดียวจาก บริบท์แบบลำดับชั้น @Binding เหมาะสำหรับการส่งข้อมูลไปยัง View ลูก, @Environment — สำหรับการเข้าถึงการตั้งค่าระบบหรือทั่วโลก

ฉันจะสร้างค่าสภาพแวดล้อมของตัวเองได้อย่างไร?

กำหนดโครงสร้างที่ใช้โปรโตคอล EnvironmentKey กับ defaultValue แบบสถิต จากนั้นขยาย EnvironmentValues ด้วยคุณสมบัติที่ใช้ getter/setter ผ่าน subscript[key] หลังการลงทะเบียน, ใช้ @Environment(\.yourKey) สำหรับอ่าน และ .environment(\.yourKey, value) สำหรับการตั้งค่า

ค่าสภาพแวดล้อมใดบ้างที่มีอยู่ใน SwiftUI?

SwiftUI มีค่าระบบมากกว่า 50 รายการ: colorScheme, locale, sizeCategory, managedObjectContext, dismiss, calendar, timeZone, horizontalSizeClass, verticalSizeClass, accessibilityEnabled, layoutDirection, legibilityWeight และอื่นๆ รายชื่อที่ครบถ้วนอยู่ในเอกสาร EnvironmentValues

@Environment ทำงานใน Preview หรือไม่?

ได้, @Environment ทำงานใน Preview แต่ค่าเริ่มต้นอาจแตกต่างจากเครื่องจำลอง สำหรับทดสอบใน Preview, ใช้ตัวแก้ไข .environment() โดยตรงในโค้ด Preview: ThemedView().environment(\.colorScheme, .dark) วิธีนี้ช่วยให้สามารถตรวจสอบสถานะของสภาพแวดล้อมต่างๆ ได้อย่างเป็นภาพ

สรุป

  • @Environment — property wrapper สำหรับอ่านค่าสภาพแวดล้อมของระบบ SwiftUI ผ่าน key path
  • โครงสี, ตำแหน่งที่อยู่, ขนาดแบบอักษร และ managedObjectContext เป็นค่าระบบที่ใช้กันมากที่สุด
  • การเปลี่ยนแปลง ค่าสภาพแวดล้อมจะทริเกอร์การเรียกโหมาระบายใหม่ของ View ที่สมัครสมาชิกทั้งหมด
  • คุณสมบัติ EnvironmentKey ที่กำหนดเอง ช่วยให้ขยายสภาพแวดล้อมแอปด้วยการตั้งค่าทั่วโลก
  • @Environment — อ่านอย่างเดียว; @EnvironmentObject — สำหรับ ObservableObject ที่มีการเข้าถึงแบบเขียน
  • ตัวแก้ไข .environment() ตั้งค่าให้กับ View ลูกในลำดับชั้น
  • ใช้ @Environment สำหรับพารามิเตอร์ระบบ, @EnvironmentObject — สำหรับ ViewModel และบริการ

เราจะพัฒนาแอปพลิเคชันบนมือถือแบบครบวงจร

IT Sectr สร้างแอปพลิเคชัน iOS และ Android สำหรับสตาร์ทอัพและธุรกิจตั้งแต่ปี 2017 เราจะให้คำแนะนำและเสนอวิธีแก้ปัญหาที่ดีที่สุดแก่คุณ

ปรึกษาโครงการ

อ่านเพิ่มเติม