@AppStorage ใน SwiftUI — คืออะไร, UserDefaults และการจัดเก็บการตั้งค่า

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

@AppStorage ใน SwiftUI เป็น property wrapper สำหรับทำงานกับ UserDefaults ที่ซิงค์ค่ากับ UI โดยอัตโนมัติ เมื่อคุณสมบัติที่ประกาศด้วย @AppStorage เปลี่ยนแปลง ค่าใหม่จะถูกบันทึกไปยัง UserDefaults ทันที และเมื่อ UserDefaults เปลี่ยนแปลงจากภายนอก — โดยวิดเจ็ตหรือส่วนขยาย — View จะถูกวาดใหม่โดยอัตโนมัติ ตาม Apple Developer Documentation (2025), @AppStorage รองรับ String, Int, Double, Bool, Data, URL และเวอร์ชันที่เป็นทางเลือก ให้การจัดเก็บการตั้งค่าผู้ใช้แบบปฏิกิริยาโดยไม่ต้องมีโค้ดสังเกตการณ์ด้วยตนเอง

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

  • @AppStorage — property wrapper สำหรับการทำงานแบบปฏิกิริยากับ UserDefaults ใน SwiftUI
  • บันทึกอัตโนมัติ — ค่าจะถูกเขียนไปยัง UserDefaults ทุกครั้งที่มีการเปลี่ยนแปลง
  • อัปเดต UI อัตโนมัติ — View จะถูกวาดใหม่เมื่อ UserDefaults เปลี่ยนแปลงจากแหล่งใดก็ได้
  • ประเภทที่รองรับ: String, Int, Double, Bool, Data, URL และเวอร์ชันทางเลือก
  • ค่าเริ่มต้น ถูกกำหนดในการประกาศและใช้ในการเปิดครั้งแรก

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

@AppStorage คือ property wrapper ที่ Apple แนะนำใน iOS 14 ซึ่งเชื่อมโยงคุณสมบัติของ View กับคีย์ใน UserDefaults เมื่ออ่านคุณสมบัติ SwiftUI จะโหลดค่าจาก UserDefaults ผ่านคีย์ที่ระบุ เมื่อเขียน จะบันทึกค่าใหม่และแจ้งให้ View ทราบว่าต้องวาดใหม่

ก่อน @AppStorage นักพัฒนาต้องอ่าน UserDefaults ด้วยตนเองใน onAppear สมัครรับ UserDefaults.didChangeNotification และอัปเดต @State เมื่อมีการเปลี่ยนแปลง @AppStorage จะทำให้วงจรทั้งหมดเป็นอัตโนมัติ: การประกาศหนึ่งบรรทัดแทนที่โค้ด boilerplate 15–20 บรรทัด นอกจากนี้ @AppStorage ยังให้การซิงค์สองทิศทาง — หากค่า UserDefaults เปลี่ยนแปลงจากกระบวนการอื่น (เช่น App Extension หรือ Widget) View ก็ยังคงได้รับการอัปเดต

ในทางสถาปัตยกรรม @AppStorage ถูกนำไปใช้เป็น DynamicProperty ซึ่งช่วยให้ SwiftUI ติดตามการพึ่งพาและวาด View ใหม่เมื่อค่าที่สังเกตเปลี่ยนแปลง ทำให้เหมาะสำหรับการจัดเก็บการตั้งค่าผู้ใช้: ภาษาอินเทอร์เฟซ การเปิด/ปิดฟีเจอร์ แท็บที่เลือกล่าสุด ชื่อผู้ใช้

@AppStorage vs UserDefaults: การเปรียบเทียบ

แม้ว่า @AppStorage จะใช้ UserDefaults ภายใน แต่แนวทางการทำงานกับพื้นที่จัดเก็บนั้นแตกต่างกันโดยพื้นฐาน UserDefaults เป็น API ระดับต่ำที่ต้องการการจัดการด้วยตนเองในการอ่าน การเขียน และการแจ้งเตือนการเปลี่ยนแปลง @AppStorage เป็นนามธรรมของ SwiftUI ที่ให้พฤติกรรมแบบปฏิกิริยาทันที

UserDefaults เหมาะสำหรับการดำเนินการครั้งเดียว: โหลดการตั้งค่าเมื่อเริ่มต้นแอป เขียนการวิเคราะห์ แคชโทเค็น @AppStorage สำหรับการตั้งค่าที่ควร อัปเดต UI แบบปฏิกิริยา: สวิตช์ธีม การเลือกภาษา การบันทึกสถานะอินเทอร์เฟซ การใช้ UserDefaults โดยตรงภายใน View เป็นปฏิปักษ์รูปแบบ เนื่องจาก View ไม่ทราบเกี่ยวกับการเปลี่ยนแปลงหากไม่สมัครรับเพิ่มเติม

พารามิเตอร์@AppStorageUserDefaults
ปฏิกิริยาอัตโนมัติต้องการสมัครรับการแจ้งเตือน
Boilerplate1 บรรทัดต่อคุณสมบัติ15–20 บรรทัดต่อคุณสมบัติ
ประเภทString, Int, Double, Bool, Data, URLทุกประเภท + วัตถุที่เก็บถาวร
ประเภทกำหนดเองผ่าน RawRepresentableผ่าน NSKeyedArchiver
App Extensionซิงค์อัตโนมัติสมัครรับด้วยตนเอง

สำหรับการตั้งค่าอย่างง่ายด้วย UI แบบปฏิกิริยา @AppStorage เป็นตัวเลือกที่ต้องการ สำหรับข้อมูลที่ซับซ้อน (อาร์เรย์ พจนานุกรม วัตถุที่กำหนดเอง) ให้ใช้ UserDefaults ร่วมกับ @State และการสมัครรับการเปลี่ยนแปลงด้วยตนเอง หรือเปลี่ยนไปใช้ SwiftData / Core Data สำหรับการจัดเก็บที่มีโครงสร้าง

ประเภทข้อมูลที่รองรับ

@AppStorage รองรับประเภทมาตรฐานที่ UserDefaults สามารถซีเรียลไลซ์ได้โดยตรง: String, Int, Double, Bool, Data, URL สำหรับแต่ละประเภทจะมีเวอร์ชันทางเลือก (String?, Int?, Double?, Bool?, Data?, URL?) ซึ่งช่วยให้แยกแยะระหว่าง "ไม่ได้ตั้งค่า" และ "ค่าว่าง"

สำหรับการจัดเก็บประเภทกำหนดเองที่สอดคล้องกับโปรโตคอล RawRepresentable @AppStorage ก็ทำงานโดยอัตโนมัติเช่นกัน หาก enum มี rawValue ประเภท String หรือ Int ก็สามารถใช้ได้โดยตรง: @AppStorage("theme") var theme: AppTheme = .system SwiftUI จะซีเรียลไลซ์/ดีซีเรียลไลซ์ค่าโดยอัตโนมัติผ่าน rawValue

swift
enum AppTheme: String {
    case system, light, dark
}

struct SettingsView: View {
    @AppStorage("username") var username: String = "Guest"
    @AppStorage("launchCount") var launchCount: Int = 0
    @AppStorage("isDarkMode") var isDarkMode: Bool = false
    @AppStorage("appTheme") var theme: AppTheme = .system
    @AppStorage("lastOpened") var lastOpened: Date? = nil

    var body: some View {
        Form {
            TextField("Username", text: $username)
            Toggle("Dark mode", isOn: $isDarkMode)
            Text("เปิดใช้งาน \(launchCount) ครั้ง")
        }
    }
}

ตัวอย่างใช้ @AppStorage ประเภทต่างๆ: String ที่มีค่าเริ่มต้น "Guest", Int สำหรับตัวนับการเปิด, Bool สำหรับธีมมืด, enum AppTheme ที่มี rawValue ประเภท String และ Date? ที่เป็นทางเลือกสำหรับเวลาที่เปิดล่าสุด แต่ละคุณสมบัติเชื่อมโยงกับ คีย์ UserDefaults ที่ระบุเป็นอาร์กิวเมนต์แรก ค่าเริ่มต้นจะถูกใช้หากไม่มีคีย์ในพื้นที่จัดเก็บในการเปิดครั้งแรก

การสังเกตการเปลี่ยนแปลง Store

ข้อดีหลักประการหนึ่งของ @AppStorage คือการสังเกตการเปลี่ยนแปลงของ UserDefaults โดยอัตโนมัติจาก แหล่งใดก็ได้ หาก App Extension หรือ Widget เปลี่ยนแปลงค่า @AppStorage ในแอปหลักจะได้รับการแจ้งเตือนและวาด View ใหม่ ซึ่งทำได้ผ่านกลไก KVO (Key-Value Observing) ที่ @AppStorage ตั้งค่าโดยอัตโนมัติบน UserDefaults.didChangeNotification

ในทางปฏิบัติหมายความว่าหากผู้ใช้เปลี่ยนการตั้งค่าใน Widget (เช่น เปิดใช้งานธีมมืด) แอปจะรับการเปลี่ยนแปลงทันที การซิงค์เดียวกันทำงานระหว่างแอปหลักและ Share Extension, Watch App หรือ Today Widget นักพัฒนาไม่จำเป็นต้องเขียนโค้ดสำหรับ การแลกเปลี่ยนข้อมูลระหว่างกระบวนการ — @AppStorage ทำโดยอัตโนมัติ

swift
struct ThemeSettingView: View {
    @AppStorage("isDarkMode") var isDarkMode: Bool = false

    var body: some View {
        VStack {
            Toggle("Dark Mode", isOn: $isDarkMode)
                .onChange(of: isDarkMode) { oldValue, newValue in
                    print("โหมดมืดเปลี่ยนเป็น \(newValue)")
                }
        }
    }
}

Toggle เชื่อมโยงกับ $isDarkMode ผ่าน @AppStorage เมื่อสลับ ค่าจะถูกบันทึกไปยัง UserDefaults โดยอัตโนมัติภายใต้คีย์ "isDarkMode" ตัวปรับแต่ง .onChange อนุญาตให้ดำเนินการผลข้างเคียงเมื่อมีการเปลี่ยนแปลง — เช่น ส่งการวิเคราะห์หรืออัปเดต UI ของหน้าจออื่น หาก Widget เปลี่ยนคีย์เดียวกัน @AppStorage จะทริกเกอร์ onChange เช่นกัน เพื่อให้มั่นใจในความสอดคล้องของสถานะ

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

มาดูหน้าจอการตั้งค่าแอปแบบเต็มรูปแบบที่ใช้ @AppStorage เพื่อจัดเก็บการกำหนดค่าทั้งหมด ฟอร์มประกอบด้วยส่วนต่าง ๆ ที่มีการตั้งค่าหลายประเภท: ฟิลด์ข้อความ สวิตช์ ตัวนับ — ค่าทั้งหมดจะถูกบันทึกไปยัง UserDefaults โดยอัตโนมัติ

swift
struct AppSettingsView: View {
    @AppStorage("displayName") var displayName = ""
    @AppStorage("notificationsEnabled") var notificationsEnabled = true
    @AppStorage("maxResults") var maxResults = 25
    @AppStorage("selectedTab") var selectedTab = "home"

    var body: some View {
        NavigationStack {
            Form {
                Section(header: Text("โปรไฟล์")) {
                    TextField("Display name", text: $displayName)
                }

                Section(header: Text("การตั้งค่า")) {
                    Toggle("Enable notifications",
                           isOn: $notificationsEnabled)
                    Stepper("Max results: \(maxResults)",
                           value: $maxResults,
                           in: 10...100,
                           step: 5)
                }

                Section {
                    Button("รีเซ็ตการตั้งค่า") {
                        UserDefaults.standard.removePersistentDomain(
                            forName: Bundle.main.bundleIdentifier!)
                    }
                    .tint(.red)
                }
            }
            .navigationTitle("Settings")
        }
    }
}

ฟอร์มประกอบด้วยคุณสมบัติ @AppStorage สี่ประเภท: String สำหรับชื่อ, Bool สำหรับการแจ้งเตือน, Int สำหรับจำนวนผลลัพธ์ และ String สำหรับแท็บที่เลือก ตัวควบคุมทั้งหมดเชื่อมโยงกับคุณสมบัติผ่าน Binding ($displayName, $notificationsEnabled ฯลฯ) ปุ่ม "Reset settings" จะล้าง UserDefaults ทั้งหมดโดยการลบโดเมนแอป — หลังจากนั้น @AppStorage จะกลับไปใช้ค่าเริ่มต้นโดยอัตโนมัติ

การซิงค์ @AppStorage กับ App Group

swift
struct SharedSettingsView: View {
    let sharedDefaults = UserDefaults(suiteName: "group.com.example.app")

    @AppStorage("widgetTheme", store: UserDefaults(suiteName: "group.com.example.app")!)
    var widgetTheme: String = "ระบบ"

    @AppStorage("widgetColor", store: UserDefaults(suiteName: "group.com.example.app")!)
    var widgetColor: String = "น้ำเงิน"

    var body: some View {
        Form {
            Picker("Widget theme", selection: $widgetTheme) {
                Text("ระบบ").tag("system")
                Text("สว่าง").tag("สว่าง")
                Text("มืด").tag("มืด")
            }
            Picker("Accent color", selection: $widgetColor) {
                Text("น้ำเงิน").tag("blue")
                Text("เขียว").tag("เขียว")
                Text("แดง").tag("แดง")
            }
        }
    }
}

สำหรับ App Group (พื้นที่จัดเก็บที่ใช้ร่วมกันระหว่างแอปและส่วนขยาย) @AppStorage ยอมรับพารามิเตอร์ store: UserDefaults(suiteName:) ค่าจะถูกบันทึกในคอนเทนเนอร์ที่ใช้ร่วมกันซึ่งมีให้สำหรับแอปหลัก, Widget, Watch App และส่วนขยายอื่น ๆ ในกลุ่มเดียวกัน Widget สามารถอ่านการตั้งค่าเหล่านี้ และเมื่อเปลี่ยนแปลงในแอป Widget จะอัปเดตโดยอัตโนมัติผ่านกลไกการสังเกต UserDefaults

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

ความแตกต่างระหว่าง @AppStorage และ @State คืออะไร?

@State เก็บค่าไว้ในหน่วยความจำเท่านั้นและถูกรีเซ็ตเมื่อรีสตาร์ทแอป @AppStorage บันทึกค่าใน UserDefaults และกู้คืนเมื่อเปิดครั้งต่อไป ใช้ @State สำหรับข้อมูลหน้าจอชั่วคราว @AppStorage สำหรับการตั้งค่าที่ควรคงอยู่หลังการรีสตาร์ท

สามารถใช้ @AppStorage กับ Enum ได้หรือไม่?

ได้ หาก Enum ใช้โปรโตคอล RawRepresentable ที่มี rawValue ประเภท String หรือ Int ตัวอย่าง: @AppStorage("theme") var theme: AppTheme = .system SwiftUI จะซีเรียลไลซ์ enum โดยอัตโนมัติผ่าน rawValue และกู้คืนเมื่อโหลด

จะล้างค่า @AppStorage ทั้งหมดได้อย่างไร?

เรียก UserDefaults.standard.removePersistentDomain(forName: Bundle.main.bundleIdentifier!) สำหรับพื้นที่จัดเก็บมาตรฐานหรือ removeObject(forKey:) สำหรับคีย์เฉพาะ หลังจากล้าง คุณสมบัติ @AppStorage ทั้งหมดจะกลับไปใช้ค่าเริ่มต้นที่ระบุในการประกาศ

@AppStorage ทำงานกับ App Extensions หรือไม่?

ได้ สำหรับการซิงค์ระหว่างแอปและส่วนขยาย ให้ใช้ App Group: @AppStorage("key", store: UserDefaults(suiteName: "group.com.example.app")!) Widget, Share Extension และ Watch App สามารถอ่านและเขียนใน UserDefaults เดียวกัน และการเปลี่ยนแปลงจะถูกติดตามโดยอัตโนมัติ

สามารถจัดเก็บข้อมูลใน @AppStorage ได้เท่าไหร่?

@AppStorage ใช้ UserDefaults ซึ่งออกแบบมาสำหรับ ข้อมูลปริมาณน้อย: การตั้งค่า โทเค็น ตัวนับ ขีดจำกัดที่แนะนำคือสูงสุด 100 KB ต่อแอป สำหรับข้อมูลที่มีโครงสร้างหรือขนาดใหญ่ (อาร์เรย์วัตถุ ไฟล์สื่อ) ให้ใช้ SwiftData, Core Data หรือระบบไฟล์

สรุป

  • @AppStorage — property wrapper สำหรับการจัดเก็บการตั้งค่าแบบปฏิกิริยาใน UserDefaults
  • บันทึกอัตโนมัติและอัปเดต UI อัตโนมัติเมื่อค่าเปลี่ยนแปลงจากแหล่งใดก็ได้
  • รองรับ String, Int, Double, Bool, Data, URL และ RawRepresentable enums
  • ค่าเริ่มต้นถูกกำหนดในการประกาศและกู้คืนเมื่อเปิดครั้งแรก
  • App Group ช่วยให้ซิงค์ @AppStorage ระหว่างแอปและส่วนขยาย
  • UserDefaults เหมาะสำหรับข้อมูลปริมาณน้อยเท่านั้น — สูงสุด 100 KB
  • ใช้ @AppStorage สำหรับการตั้งค่าผู้ใช้ @State สำหรับสถานะหน้าจอชั่วคราว

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

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

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

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