willSet และ didSet ใน Swift: คืออะไร ไวยากรณ์ และการทำงานของผู้สังเกตการณ์

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

willSet และ didSet คือผู้สังเกตการณ์คุณสมบัติ (property observers) ใน Swift ที่ช่วยให้สามารถรันโค้ดก่อนและหลังการเปลี่ยนแปลงค่าของคุณสมบัติ ต่างจาก computed properties ตรงที่ผู้สังเกตการณ์ไม่ได้คำนวณค่าใหม่ แต่เพียงตอบสนองต่อการเปลี่ยนแปลงเท่านั้น ตามเอกสารของ Apple, The Swift Programming Language (2026) ผู้สังเกตการณ์เป็นสิ่งที่ขาดไม่ได้สำหรับการตรวจสอบความถูกต้องของข้อมูล การซิงโครไนซ์อินเทอร์เฟซ และการบันทึกการเปลี่ยนแปลงในโค้ด

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

  • willSet — ถูกเรียกก่อนบันทึกค่าใหม่ของคุณสมบัติ
  • didSet — ถูกเรียกหลังจากบันทึกค่าใหม่
  • newValue — พารามิเตอร์โดยนัยใน willSet ที่มีค่าใหม่
  • oldValue — พารามิเตอร์โดยนัยใน didSet ที่มีค่าเก่า
  • ผู้สังเกตการณ์ — ไม่ทำงานระหว่างการเริ่มต้นและภายใน init

willSet และ didSet ใน Swift คืออะไร?

willSet และ didSet คือผู้สังเกตการณ์คุณสมบัติ (property observers) ใน Swift ซึ่งเป็นกลไกในตัวสำหรับติดตามการเปลี่ยนแปลงของ stored properties

ต่างจากภาษาที่อื่นที่ต้องมีการใช้งาน setter ด้วยตนเองหรือระบบ callback Swift มีไวยากรณ์แบบประกาศ (declarative) สำหรับตอบสนองต่อการเปลี่ยนแปลง ผู้สังเกตการณ์จะถูกเพิ่มหลังจากการประกาศคุณสมบัติโดยตรง และไม่จำเป็นต้องเรียกแยกต่างหาก

ตามเอกสารสำหรับนักพัฒนา Apple (2026) property observers รองรับ stored properties ของคลาส โครงสร้าง หรือการแจกแจงใด ๆ พวกมันไม่ทำงานกับ computed properties เพราะคุณสมบัติเหล่านี้ไม่ได้เก็บค่า — สำหรับพวกมัน การตอบสนองต่อการเปลี่ยนแปลงจะถูกใช้งานโดยตรงใน setter

เมื่อใดที่ willSet ถูกเรียก

willSet ถูกเรียกทันทีก่อนกำหนดค่าใหม่ให้กับคุณสมบัติ ภายใน willSet มีพารามิเตอร์โดยนัย newValue ซึ่งมีค่าที่จะถูกตั้งค่า ในขณะนี้ ค่าปัจจุบันของคุณสมบัติยังไม่เปลี่ยนแปลง — คุณสามารถอ่านค่าเก่าได้โดยตรงผ่านคุณสมบัติ

ตามข้อเสนอ Swift Evolution SE-0001 (2024) willSet ให้ความสามารถในการดำเนินการตรวจสอบความถูกต้องหรือบันทึกก่อนการเปลี่ยนแปลงจริง ถ้ามีข้อยกเว้นถูกโยนใน willSet ค่าใหม่จะไม่ถูกนำไปใช้ ทำให้ผู้สังเกตการณ์เป็นกลไกป้องกันข้อมูล

เมื่อใดที่ didSet ถูกเรียก

didSet ถูกเรียกทันทีหลังจากกำหนดค่าใหม่ ภายใน didSet มีพารามิเตอร์โดยนัย oldValue ซึ่งมีค่าก่อนการเปลี่ยนแปลง ในจุดนี้ คุณสมบัติมีค่าใหม่แล้ว และคุณสามารถเปรียบเทียบกับค่าเก่าได้

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

ไวยากรณ์ของผู้สังเกตการณ์คุณสมบัติ

Property observers ถูกประกาศทันทีหลังจากคุณสมบัติโดยใช้วงเล็บปีกกา ไวยากรณ์ขั้นต่ำต้องการผู้สังเกตการณ์เพียงตัวเดียว แต่คุณสามารถประกาศทั้งสองได้

swift
var score: Int = 0 {
    willSet {
        print("คะแนนจะเปลี่ยนเป็น \(newValue)")
    }
    didSet {
        print("คะแนนเปลี่ยนจาก \(oldValue) เป็น \(score)")
    }
}

ทั้งสอง ผู้สังเกตการณ์เป็นตัวเลือก — คุณสามารถระบุเฉพาะ willSet หรือเฉพาะ didSet สำหรับ willSet คุณสามารถเปลี่ยนชื่อ newValue โดยการระบุชื่อในวงเล็บ

swift
var username: String = "guest" {
    willSet(newName) {
        print("กำลังจะตั้งค่า \(newName)")
    }
    didSet(oldName) {
        print("เดิมคือ \(oldName) ตอนนี้คือ \(username)")
    }
}

ตาม Swift Language Guide (2026) การเปลี่ยนชื่อพารามิเตอร์ช่วยปรับปรุงความสามารถในการอ่านโค้ด โดยเฉพาะเมื่อคุณสมบัติและผู้สังเกตการณ์ถูกใช้ในโปรเจ็กต์ขนาดใหญ่ที่มีชื่อยาว

วิธีการทำงานของ willSet และ didSet

ลำดับการทำงานถูกกำหนดอย่างเคร่งครัด: อันดับแรก willSet (ค่าเก่าพร้อมใช้งาน) จากนั้นกำหนดค่า จากนั้น didSet (ค่าใหม่พร้อมใช้งาน)

swift
class Temperature {
    var celsius: Double = 0.0 {
        willSet {
            print("อุณหภูมิจะเปลี่ยนจาก \(celsius) เป็น \(newValue)")
        }
        didSet {
            if celsius > 100.0 {
                print("เกินจุดเดือดแล้ว!")
            }
        }
    }
}

ข้อจำกัดที่สำคัญ: ผู้สังเกตการณ์จะไม่ถูกเรียกระหว่างการเริ่มต้นคุณสมบัติเมื่อสร้างอินสแตนซ์ ภายใน init การกำหนดค่าไม่ทริกเกอร์ willSet และ didSet — ซึ่งป้องกันผลข้างเคียงที่ไม่พึงประสงค์ในขั้นตอนการสร้าง

ตาม Apple Swift Blog (2025) พฤติกรรมนี้แตกต่างจากหลายภาษาที่ setter ถูกเรียกแม้ในคอนสตรัคเตอร์ Swift เลือกความปลอดภัย: ผู้สังเกตการณ์จะเริ่มทำงานหลังจากเสร็จสิ้นการเริ่มต้นวัตถุเท่านั้น

การเรียกซ้อนและการเรียกซ้ำ

การเปลี่ยนแปลงคุณสมบัติภายใน didSet อาจทำให้เกิดการเรียกผู้สังเกตการณ์ซ้ำ ๆ Swift ไม่บล็อกการเรียกซ้ำ — โปรแกรมเมอร์ต้องควบคุมด้วยตนเอง

swift
var counter: Int = 0 {
    didSet {
        if counter < 5 {
            counter += 1
        }
    }
}

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

ผู้สังเกตการณ์สำหรับคุณสมบัติของโครงสร้าง

โครงสร้างรองรับ willSet และ didSet สำหรับ stored โดยไม่มีข้อจำกัด สิ่งสำคัญคือต้องจำว่าโครงสร้างเป็นชนิดค่า (value types) และการแก้ไขคุณสมบัติภายในเมธอด mutating ก็ทริกเกอร์ผู้สังเกตการณ์เช่นกัน

swift
struct Point {
    var x: Double = 0.0 {
        didSet {
            print("X เปลี่ยนเป็น \(x)")
        }
    }
    var y: Double = 0.0 {
        didSet {
            print("Y เปลี่ยนเป็น \(y)")
        }
    }
}

var point = Point()
point.x = 5.0

การใช้ผู้สังเกตการณ์ในโปรเจ็กต์จริง

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

การตรวจสอบค่าความถูกต้อง

didSet ช่วยให้คุณย้อนกลับหรือแก้ไขค่าที่ไม่ถูกต้องทันทีหลังจากตั้งค่า ซึ่งแทนที่ setter ที่ยุ่งยากใน Objective-C และรับประกันความสมบูรณ์ของข้อมูลในระดับโมเดล

swift
var age: Int = 0 {
    didSet {
        if age < 0 || age > 150 {
            age = oldValue
        }
    }
}

การซิงโครไนซ์อินเทอร์เฟซผู้ใช้

เมื่อคุณสมบัติที่เกี่ยวข้องเปลี่ยนแปลง คุณสามารถอัปเดตองค์ประกอบอินเทอร์เฟซโดยอัตโนมัติโดยไม่ต้องเรียกเมธอดอัปเดตแยกต่างหาก

swift
var userName: String = "" {
    didSet {
        nameLabel.text = userName
    }
}

การบันทึกการเปลี่ยนแปลง

willSet สะดวกสำหรับการบันทึกเพื่อวัตถุประสงค์ในการดีบักหรือตรวจสอบ คุณสามารถบันทึกเวลาและค่าใหม่ก่อนที่จะถูกนำไปใช้ เพื่อให้แน่ใจว่าล็อกมีข้อมูลต้นฉบับสำหรับการวิเคราะห์

ตาม objc.io (2025) property observers มีประโยชน์อย่างยิ่งในสถาปัตยกรรมที่มีการไหลของข้อมูลทิศทางเดียว ซึ่งทุกการเปลี่ยนแปลงคุณสมบัติจะถูกบันทึกสำหรับการสร้างสถานะใหม่ในภายหลัง

เปรียบเทียบกับ computed properties

Computed properties คำนวณค่าทันทีและไม่มีพื้นที่จัดเก็บ ในขณะที่ willSet และ didSet ทำงานบน stored property ที่มีค่าจริง

ลักษณะProperty ObserversComputed Properties
เก็บค่าใช่ไม่
รันโค้ดเมื่อเปลี่ยนแปลงใช่ไม่
ประเภทการประกาศvarvar (get/set)
พารามิเตอร์การเข้าถึงnewValue, oldValuenewValue (ใน set)
การเริ่มต้นต้องการค่าเริ่มต้นไม่ต้องการ

ความแตกต่างสำคัญ: computed property คำนวณค่าในทุกการเข้าถึง ในขณะที่ property observer ตอบสนองต่อการเปลี่ยนแปลงของค่าที่มีอยู่ การเลือกระหว่างพวกมันขึ้นอยู่กับความหมาย — ถ้าคุณสมบัติได้มาจากข้อมูลอื่น ให้ใช้ computed ถ้ามันเป็นค่าอิสระที่ต้องสังเกตการเปลี่ยนแปลง ให้ใช้ willSet/didSet

ข้อผิดพลาดทั่วไปเมื่อใช้งาน

ข้อผิดพลาดที่พบบ่อยที่สุดคือการเรียก didSet แบบเรียกซ้ำโดยไม่มีเงื่อนไขออก ทุกการเปลี่ยนแปลงคุณสมบัติภายใน didSet จะทริกเกอร์ผู้สังเกตการณ์อีกครั้ง นำไปสู่ลูปไม่สิ้นสุด

ข้อผิดพลาดที่พบบ่อยอันดับสองคือการพยายามใช้ผู้สังเกตการณ์บนคุณสมบัติ let คอมไพเลอร์ Swift จะแสดงข้อผิดพลาดเพราะ let เป็นค่าคงที่

ข้อผิดพลาดที่สามคือการละเลยว่าผู้สังเกตการณ์จะไม่ถูกเรียกระหว่างการเริ่มต้น นักพัฒนาที่คาดหวังว่า willSet จะทำงานภายใน init จะได้รับพฤติกรรมที่ไม่คาดคิด

ปัญหาที่สี่คือการประยุกต์ใช้ผู้สังเกตการณ์กับคุณสมบัติใน extension Swift ห้ามเพิ่ม willSet/didSet ให้กับ stored properties ใน extension

ตาม Ray Wenderlich (2025) การเข้าใจข้อจำกัดเหล่านี้ช่วยหลีกเลี่ยงข้อบกพร่องในระยะเริ่มต้นและทำให้โค้ด Swift คาดการณ์ได้มากขึ้น

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

สามารถใช้ willSet โดยไม่มี didSet ได้หรือไม่?

ได้ ผู้สังเกตการณ์แต่ละตัวเป็นตัวเลือก คุณสามารถประกาศเฉพาะ willSet เฉพาะ didSet หรือทั้งสองอย่างพร้อมกัน

ผู้สังเกตการณ์ทำงานใน extension หรือไม่?

ไม่ Swift ห้ามเพิ่ม willSet และ didSet ใน extension สำหรับ stored properties ผู้สังเกตการณ์จะถูกประกาศเฉพาะในนิยามชนิดดั้งเดิมเท่านั้น

ผู้สังเกตการณ์ถูกเรียกเมื่อเปลี่ยนคุณสมบัติภายใน init หรือไม่?

ไม่ ระหว่างการเริ่มต้น ผู้สังเกตการณ์จะไม่ถูกเรียก นี่เป็นกลไกป้องกันที่ป้องกันผลข้างเคียงในขั้นตอนการสร้างวัตถุ

willSet แตกต่างจาก setter ใน computed property อย่างไร?

willSet คือผู้สังเกตการณ์ stored property ที่ทำงานก่อนการเปลี่ยนแปลงค่า setter ใน computed property เป็นวิธีคำนวณค่าใหม่ ไม่ใช่การสังเกตค่าที่มีอยู่

จะเกิดอะไรขึ้นเมื่อเปลี่ยนคุณสมบัติภายใน didSet?

การเรียก didSet ซ้ำจะทำให้เกิดการเรียกซ้ำ หากไม่มีเงื่อนไขออก จะนำไปสู่สแต็กโอเวอร์โฟลว์และการสิ้นสุดโปรแกรม

สรุป

  • willSet — ผู้สังเกตการณ์ที่ทำงานก่อนคุณสมบัติเปลี่ยนแปลง สามารถเข้าถึง newValue
  • didSet — ผู้สังเกตการณ์ที่ทำงานหลังจากคุณสมบัติเปลี่ยนแปลง สามารถเข้าถึง oldValue
  • ไวยากรณ์ — ผู้สังเกตการณ์ประกาศในวงเล็บปีกกาหลังจากการประกาศคุณสมบัติ
  • การเริ่มต้น — ผู้สังเกตการณ์ไม่ทำงานภายใน init และเมื่อตั้งค่าเริ่มต้น
  • การใช้งาน — การตรวจสอบ การซิงโครไนซ์อินเทอร์เฟซผู้ใช้ การบันทึก การตรวจสอบการเปลี่ยนแปลง
  • การเรียกซ้ำ — การเปลี่ยนคุณสมบัติภายใน didSet ต้องมีเงื่อนไขออกอย่างชัดเจน
  • Computed — อย่าสับสนกับ computed properties: ผู้สังเกตการณ์สังเกต computed คำนวณ

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

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

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

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