@State — วัตถุประสงค์และการใช้งานใน SwiftUI

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

@State คือ Property Wrapper ใน SwiftUI สำหรับจัดการสถานะภายในเครื่องภายในวิวเดียว SwiftUI จะวาดวิวใหม่โดยอัตโนมัติทุกครั้งที่คุณสมบัติ @State เปลี่ยนแปลง ทำให้อินเทอร์เฟสตอบสนองได้โดยไม่ต้องเรียกการอัปเดตด้วยตนเอง ตาม Apple Developer Documentation (2025) @State ถูกแนะนำสำหรับชนิดข้อมูลอย่างง่ายและโครงสร้างที่เป็นของวิวเดียว @State เป็นวิธีที่ง่ายที่สุดในการเพิ่มการโต้ตอบให้กับอินเทอร์เฟส SwiftUI

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

  • @State — Property Wrapper สำหรับสถานะภายในเครื่องที่เป็นของวิวเดียว
  • การอัปเดตอัตโนมัติ — SwiftUI เรียก body ใหม่เมื่อคุณสมบัติ @State เปลี่ยนแปลง
  • ชนิดข้อมูลอย่างง่าย — @State ทำงานกับ String, Int, Bool, enum และ struct
  • ไม่ส่งต่อไปยังวิวลูก — ใช้ @Binding สำหรับการเปลี่ยนแปลงจากคอมโพเนนต์ลูก
  • private — คุณสมบัติ @State ถูกประกาศด้วยตัวปรับแต่ง private เสมอ

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

@State คือ Property Wrapper ที่สร้างไว้ใน SwiftUI ซึ่งช่วยให้วิวจัดเก็บและติดตามสถานะของตัวเองได้ เมื่อค่า @State เปลี่ยนแปลง SwiftUI จะวาดวิวใหม่โดยอัตโนมัติโดยเรียกคุณสมบัติ body อีกครั้ง นี่คือพื้นฐานของการเขียนโปรแกรมเชิงตอบสนองใน SwiftUI: นักพัฒนาประกาศสถานะ และเฟรมเวิร์กจัดการการซิงโครไนซ์อินเทอร์เฟส

@State สร้างพื้นที่จัดเก็บในฮีปที่จัดการโดย SwiftUI พื้นที่นี้ คงอยู่ — มันรอดจากการเริ่มต้นซ้ำของโครงสร้างวิวที่เกิดขึ้นในทุกการเรนเดอร์ SwiftUI ใช้ตัวระบุของวิว (สร้างจากตำแหน่งในลำดับชั้น) เพื่อผูกคุณสมบัติ @State กับวิวเฉพาะ ด้วยเหตุนี้ สถานะจึงไม่ถูกรีเซ็ตเมื่อวิวพ่อแม่ถูกอัปเดต

ข้อจำกัดที่สำคัญ: @State มีไว้สำหรับ ชนิดข้อมูลแบบค่า (struct, enum, ชนิดพื้นฐาน) เท่านั้น สำหรับชนิดข้อมูลแบบอ้างอิง (คลาส) ให้ใช้ @StateObject หรือ @ObservedObject หากคุณกำหนดคลาสให้กับคุณสมบัติ @State SwiftUI จะไม่สามารถตรวจจับการเปลี่ยนแปลงภายในออบเจกต์ได้ — มีเพียงการแทนที่การอ้างอิงทั้งหมด

@State ทำงานอย่างไรภายใต้ฝาครอบ?

SwiftUI ใช้งาน @State ผ่านกลไก Storage ภายใน แต่ละคุณสมบัติ @State จะได้รับเซลล์หน่วยความจำเฉพาะที่เก็บไว้ในคอนเทนเนอร์จัดเก็บพิเศษของวิว เมื่อเกิดการเขียนไปยัง wrappedValue SwiftUI จะแจ้งกราฟการพึ่งพาของมันผ่าน didSet เกี่ยวกับความจำเป็นในการวาดใหม่

swift
struct ContentView: View {
    @State private var name: String = "User"
    @State private var isLoggedIn: Bool = false

    var body: some View {
        VStack {
            Text("สวัสดี, \(name)")
            Button(isLoggedIn ? "ออกจากระบบ" : "เข้าสู่ระบบ") {
                isLoggedIn.toggle()
            }
        }
    }
}

ในตัวอย่าง มีสองคุณสมบัติ @State: name (String) และ isLoggedIn (Bool) เมื่อ isLoggedIn.toggle() ถูกเรียก SwiftUI จะทำเครื่องหมาย ContentView ว่าต้องการการอัปเดตและเรียก body อีกครั้งในรอบการเรนเดอร์ถัดไป จุดสำคัญ: คุณสมบัติ @State ถูกประกาศด้วยตัวปรับแต่ง private เสมอ — นี่เป็นสัญญาณว่าสถานะเป็นของวิวปัจจุบันโดยเฉพาะและไม่ควรถูกเปลี่ยนแปลงจากภายนอกโดยตรง

สำหรับการสังเกตการเปลี่ยนแปลง SwiftUI ใช้ CurrentValueSubject จาก Combine แต่ละคุณสมบัติ @State จะสร้างผู้เผยแพร่ที่ซ่อนอยู่ซึ่งแจ้งระบบทุกครั้งที่มีการเปลี่ยนแปลง ซึ่งช่วยให้ SwiftUI วาดเฉพาะชุดวิวที่จำเป็นน้อยที่สุดเท่านั้น หลีกเลี่ยงการอัปเดตลำดับชั้นทั้งหมด

เมื่อใดควรใช้ @State ในโปรเจกต์

@State เหมาะที่สุดสำหรับ สถานะภายในเครื่องอย่างง่าย: ฟิลด์ข้อความในการค้นหา ธงบูลีนสำหรับหน้าต่างโมดัล สวิตช์การตั้งค่า ตัวนับ รายการที่ถูกเลือกในรายการ หากค่าใช้ในวิวเดียวและคอมโพเนนต์ลูกของมัน (ผ่าน @Binding) @State คือตัวเลือกที่ถูกต้อง สำหรับสถานะที่ต้องอยู่รอดเมื่อวิวปิด (เช่น ข้อมูลฟอร์ม) @State ก็ทำงานเช่นกันตราบใดที่วิวยังคงอยู่ในลำดับชั้น

  • ฟิลด์ข้อความ — @State สำหรับจัดเก็บข้อความที่ป้อนใน TextField
  • ธงบูลีน — @State สำหรับแสดง/ซ่อนหน้าต่างโมดัลและชีต
  • การเลือกรายการ — @State สำหรับติดตามแท็บหรือแถวที่เลือก
  • ตัวนับ — @State สำหรับค่าตัวเลขที่มีการเพิ่ม/ลด
  • การคำนวณระหว่างกลาง — @State สำหรับแคชผลลัพธ์ภายในวิว

อย่าใช้ @State สำหรับ สถานะทั่วโลก ของแอปพลิเคชัน การแคชข้อมูลเครือข่าย หรือออบเจกต์ที่ใช้ในหลายหน้าจอ @StateObject และ @EnvironmentObject ถูกออกแบบมาเพื่อวัตถุประสงค์เหล่านี้ นอกจากนี้ @State ไม่เหมาะสำหรับการจัดเก็บข้อมูลจำนวนมาก — ทุกการเปลี่ยนแปลงจะวาดวิวทั้งหมดใหม่

@State และ @Binding: การทำงานร่วมกัน

@Binding คือสะพานระหว่าง @State ในวิวพ่อแม่และวิวลูกที่ต้องการเปลี่ยนแปลงสถานะนั้น พ่อแม่ประกาศ @State และคอมโพเนนต์ลูกได้รับ Binding ผ่านการฉาย $ การเปลี่ยน Binding ในวิวลูกจะอัปเดต @State ในพ่อแม่โดยอัตโนมัติ — และในทางกลับกัน ซึ่งรับประกันการไหลของข้อมูลทางเดียวที่มีความสามารถในการตอบกลับ

swift
struct ParentView: View {
    @State private var text: String = ""

    var body: some View {
        ChildView(text: $text)
    }
}

struct ChildView: View {
    @Binding var text: String

    var body: some View {
        TextField("Enter text", text: $text)
    }
}

ในลิสติ้ง ParentView เป็นเจ้าของ @State text และ ChildView ได้รับ $text เป็น Binding TextField ภายใน ChildView ผูกกับ Binding นี้ผ่าน text: $text เมื่อผู้ใช้พิมพ์ใน TextField ค่าจะเปลี่ยนแปลงใน ChildView ผ่าน Binding ซึ่งทำให้เกิดการอัปเดต @State ใน ParentView วิวทั้งสองจะถูกวาดใหม่ด้วยค่าใหม่

ข้อผิดพลาดทั่วไปเมื่อทำงานกับ @State

ข้อผิดพลาดที่พบบ่อยที่สุดคือการกำหนด คลาส ให้กับคุณสมบัติ @State หากคุณเขียน @State var model = MyClass() SwiftUI จะไม่สามารถติดตามการเปลี่ยนแปลงของคุณสมบัติภายในคลาสได้ — มีเพียงการแทนที่ออบเจกต์ สำหรับคลาส ให้ใช้ @StateObject เสมอ ปัญหาทั่วไปที่สองคือการประกาศ @State โดยไม่มีตัวปรับแต่ง private ซึ่งละเมิดหลักการของการห่อหุ้มสถานะ

การส่ง @State โดยตรง ไปยังวิวลูกโดยไม่มี $ เป็นข้อผิดพลาดทั่วไปอีกอย่างหนึ่ง หากคุณส่ง TextField(text: text) แทน TextField(text: $text) คอมโพเนนต์ลูกจะได้รับเพียงสตริง ไม่ใช่ Binding การเปลี่ยนแปลงข้อความใน TextField จะไม่ถูกซิงโครไนซ์กับ @State ของพ่อแม่ ใช้การฉาย $ เสมอเพื่อส่ง Binding

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

ตัวอย่างการใช้ @State ใน SwiftUI

@State ถูกใช้ในโปรเจกต์ SwiftUI ส่วนใหญ่สำหรับการโต้ตอบพื้นฐาน พิจารณาตัวอย่างฟอร์มเข้าสู่ระบบที่ @State จัดการฟิลด์ข้อความและสถานะการโหลด รูปแบบนี้ปรากฏในทุกแอปพลิเคชัน — จากโน้ตง่าย ๆ ไปจนถึงโซลูชันองค์กรที่ซับซ้อน

swift
struct LoginView: View {
    @State private var email: String = ""
    @State private var password: String = ""
    @State private var isLoading: Bool = false
    @State private var errorMessage: String?

    var body: some View {
        Form {
            TextField("Email", text: $email)
            SecureField("Password", text: $password)
            Button("เข้าสู่ระบบ") {
                login()
            }.disabled(isLoading)
        }
    }

    private func login() {
        isLoading = true
        // ดำเนินการคำขอเครือข่าย
    }
}

ในตัวอย่าง มีสี่คุณสมบัติ @State: email และ password สำหรับฟิลด์ฟอร์ม isLoading สำหรับการบ่งชี้การโหลด และ errorMessage สำหรับการแสดงข้อผิดพลาด แต่ละคุณสมบัติจัดการส่วนของอินเทอร์เฟสอย่างอิสระ เมื่อ isLoading เปลี่ยนแปลง ปุ่มจะถูกปิดใช้งานโดยอัตโนมัติผ่าน disabled(isLoading) — โดยไม่ต้องอัปเดต UI ด้วยตนเอง

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

ทำไม @State ถึงถูกประกาศด้วย private?

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

@State สามารถเก็บอาร์เรย์หรือดิกชันนารีได้หรือไม่?

ใช่ @State รองรับอาร์เรย์และดิกชันนารีเพราะ它们是ชนิดข้อมูลแบบค่า อย่างไรก็ตาม เมื่อสมาชิกของอาร์เรย์เปลี่ยนแปลง SwiftUI จะวาดวิวทั้งหมดใหม่ สำหรับลิสต์ขนาดใหญ่ @StateObject กับ @Published มีประสิทธิภาพมากกว่า

จะเกิดอะไรขึ้นเมื่อกำหนด nil ให้กับคุณสมบัติ @State ที่มีชนิด Optional?

@State ทำงานได้อย่างถูกต้องกับชนิด Optional เมื่อ nil ถูกกำหนด SwiftUI จะตรวจจับการเปลี่ยนแปลงและวาดวิวใหม่ ซึ่งสะดวกสำหรับสถานะเช่น errorMessage: String? โดยที่ nil หมายถึงไม่มีข้อผิดพลาด

@State มีพฤติกรรมอย่างไรเมื่อวิวปรากฏอีกครั้ง?

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

สามารถทำให้การเปลี่ยนแปลง @State เป็นแอนิเมชันได้หรือไม่?

ใช่ ห่อการเปลี่ยนแปลงใน withAnimation: withAnimation(.easeInOut) { isExpanded.toggle() } SwiftUI จะทำให้การเปลี่ยนผ่านระหว่างสถานะอินเทอร์เฟสเก่าและใหม่เป็นแอนิเมชันด้วยชนิดแอนิเมชันที่ระบุ

สรุป

  • @State — Property Wrapper สำหรับสถานะภายในเครื่องของวิวเดียว อัปเดตอินเทอร์เฟสโดยอัตโนมัติ
  • ทำงานกับ ชนิดข้อมูลอย่างง่าย: String, Int, Bool รวมถึง struct และ enum
  • ไม่ทำงานกับ ชนิดข้อมูลแบบอ้างอิง (คลาส) — ใช้ @StateObject
  • private เสมอ — สถานะไม่ควรถูกเปลี่ยนแปลงจากภายนอกโดยตรง
  • การฉาย $ — สร้าง Binding สำหรับส่งสิทธิ์การเปลี่ยนแปลงไปยังวิวลูก
  • หลาย @State ในวิวเดียว — ปฏิบัติปกติสำหรับสถานะอิสระ
  • withAnimation — อนุญาตให้ทำแอนิเมชันการเปลี่ยนแปลงคุณสมบัติ @State

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

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

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

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