Lazy Property ใน Swift: คืออะไรและไวยากรณ์ของการเริ่มต้นแบบขี้เกียจ

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

Lazy Property ใน Swift เป็นกลไกการเริ่มต้นแบบหน่วงเวลา โดยคุณสมบัติจะถูกคำนวณ ณ เวลาที่มีการเข้าถึงครั้งแรก แทนที่จะเป็นตอนที่สร้างอ็อบเจกต์ แตกต่างจากคุณสมบัติที่เก็บข้อมูลทั่วไป ตัวแปร lazy สามารถลดเวลาเริ่มต้นและการใช้หน่วยความจำสำหรับการดำเนินงานที่ใช้ทรัพยากรมากได้อย่างมีนัยสำคัญ ตามเอกสารของนักพัฒนา Apple (2026) คุณสมบัติ lazy รับประกันว่าจะเริ่มต้นเพียงครั้งเดียวและปลอดภัยต่อเธรดในการเข้าถึงครั้งแรก

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

  • Lazy — คุณสมบัติเริ่มต้นในการเข้าถึงครั้งแรก ไม่ใช่ตอนสร้างอ็อบเจกต์
  • เฉพาะ var — lazy ไม่อนุญาตให้ใช้กับ let เนื่องจากค่าคงที่ต้องทราบก่อนการเริ่มต้น
  • ความปลอดภัยของเธรด — การเริ่มต้นคุณสมบัติ lazy ถูกซิงโครไนซ์ แต่การเข้าถึงครั้งต่อไปไม่
  • ครั้งเดียว — lazy ถูกคำนวณเพียงครั้งเดียว การเข้าถึงครั้งต่อไปจะคืนค่าที่เก็บไว้
  • การปรับให้เหมาะสม — ลดเวลาเริ่มต้นและการใช้หน่วยความจำสำหรับข้อมูลที่ใช้งานน้อย

Lazy Property ใน Swift คืออะไร?

Lazy Property คือคุณสมบัติที่เก็บข้อมูลซึ่งการเริ่มต้นถูกหน่วงเวลาจนกว่าจะมีการเข้าถึงครั้งแรก คำสำคัญ lazy ก่อนการประกาศ var บอกให้คอมไพเลอร์ไม่คำนวณค่าเมื่อสร้างอ็อบเจกต์

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

ตาม Swift by Sundell (2025) คุณสมบัติ lazy เป็นหนึ่งในเครื่องมือปรับประสิทธิภาพที่มีประสิทธิภาพมากที่สุดในแอปพลิเคชัน iOS สามารถ ลด เวลาเริ่มต้นลง 20–40% ในแอปที่มีการตั้งค่าเริ่มต้นหนัก เช่น โปรแกรมแก้ไขกราฟิกหรือแดชบอร์ดวิเคราะห์

ไวยากรณ์ของคุณสมบัติ lazy

การประกาศคุณสมบัติ lazy ต้องใช้คำสำคัญ lazy ก่อน var ค่าถูกกำหนดผ่านคลอเชอร์หรือการเรียกใช้ฟังก์ชัน

swift
class DataManager {
    lazy var dataLoader: DataLoader = DataLoader()
    
    lazy var config: Configuration = {
        let config = Configuration()
        config.loadDefaults()
        return config
    }()
}

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

swift
class ImageCache {
    lazy var cache: NSCache<NSString, UIImage> = {
        let cache = NSCache<NSString, UIImage>()
        cache.countLimit = 100
        cache.totalCostLimit = 50 * 1024 * 1024
        return cache
    }()
}

คุณสมบัติ lazy หลายตัวเริ่มต้นอย่างอิสระจากกัน หากคุณสมบัติ lazy สองตัวอ้างอิงถึงกันผ่านคลอเชอร์ จะเกิดการพึ่งพาแบบวนซ้ำซึ่ง Swift ไม่สามารถแก้ไขได้โดยอัตโนมัติ

เมื่อใดที่คุณสมบัติ lazy เริ่มต้น

ช่วงเวลา ของการเริ่มต้นคือความแตกต่างหลักระหว่าง lazy และคุณสมบัติที่เก็บข้อมูลทั่วไป การเริ่มต้นเกิดขึ้นเมื่อมีการอ่านหรือเขียนคุณสมบัติครั้งแรก แต่ไม่ก่อนหน้านั้น

การเข้าถึงครั้งแรก (อ่านหรือเขียน)

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

swift
class ReportGenerator {
    lazy var report: String = {
        print("กำลังสร้างรายงาน...")
        return "Annual report data"
    }()
}

let generator = ReportGenerator()
// ยังไม่ได้สร้างรายงาน ณ จุดนี้
print(generator.report)  // "กำลังสร้างรายงาน..."
print(generator.report)  // ไม่ถูกสร้างใหม่ในการเข้าถึงครั้งต่อไป

พฤติกรรมกับการสืบทอด

คุณสมบัติ lazy ไม่สามารถถูกแทนที่ในคลาสย่อยได้ หากคลาสประกาศคุณสมบัติ lazy คลาสลูกไม่สามารถแทนที่มันเป็นคุณสมบัติที่คำนวณหรือที่เก็บข้อมูลที่มีพฤติกรรมแตกต่าง

ตาม Apple Swift Blog (2025) ข้อจำกัดนี้เกิดจากที่ lazy ไม่ใช่ตัวปรับเปลี่ยนการแทนที่ แต่เป็นรายละเอียดการจัดเก็บข้อมูล คลาสย่อยสามารถแทนที่เฉพาะเมธอดที่คุณสมบัติ lazy เรียกในคลอเชอร์ของมันเท่านั้น

ความปลอดภัยของเธรดของคุณสมบัติ lazy

การเริ่มต้นของคุณสมบัติ lazy ปลอดภัยต่อเธรดใน Swift: หากสองเธรดเข้าถึงคุณสมบัติ lazy พร้อมกัน การเริ่มต้นจะเกิดขึ้นเพียงครั้งเดียว และเธรดที่สองจะถูกบล็อกจนกว่าจะเสร็จสมบูรณ์

อย่างไรก็ตาม การซิงโครไนซ์จะถูกยกเลิกหลังจากการเริ่มต้น ซึ่งหมายความว่าการอ่านพร้อมกันจากหลายเธรดปลอดภัย แต่หากเธรดหนึ่งเขียนค่าใหม่ลงใน lazy var ในขณะที่อีกเธรดอ่าน จะเกิด การแข่งข้อมูล

ตามข้อเสนอ Swift Evolution SE-0254 (2025) กลไกการซิงโครไนซ์สำหรับคุณสมบัติ lazy ถูกนำไปใช้ผ่าน objc_sync_enter/exit ในระดับต่ำ สิ่งนี้รับประกันการเริ่มต้นแบบอะตอมมิก แต่ไม่รับประกันการเปลี่ยนแปลงในภายหลัง สำหรับการทำงานที่ ปลอดภัยต่อเธรดกับคุณสมบัติ lazy ที่เปลี่ยนแปลงได้ ให้ใช้กลไกการซิงโครไนซ์แยกต่างหาก

กรณีการใช้งานจริง

คุณสมบัติ lazy ถูกใช้ในโปรเจกต์ Swift เพื่อเพิ่มประสิทธิภาพและปรับปรุงสถาปัตยกรรมโค้ด

ทรัพยากรหนัก

การโหลดรูปภาพ การแยกวิเคราะห์ JSON การทำงานกับฐานข้อมูล — การดำเนินการทั้งหมดนี้สามารถหน่วงเวลาโดยใช้ lazy จนกว่าผู้ใช้ต้องการข้อมูลจริงๆ

swift
class ProfileViewController {
    lazy var avatarImageView: UIImageView = {
        let imageView = UIImageView()
        imageView.contentMode = .scaleAspectFill
        imageView.clipsToBounds = true
        return imageView
    }()
}

การพึ่งพา singleton

บริการ และตัวจัดการที่ไม่จำเป็นทันทีเมื่อเริ่มต้นแอป ประกาศเป็น lazy ได้อย่างมีประสิทธิภาพ ซึ่งช่วยลดเวลาเริ่มต้นและการใช้หน่วยความจำ

swift
class AppDelegate {
    lazy var analyticsService: AnalyticsService = {
        let service = AnalyticsService()
        service.configure()
        return service
    }()
    
    lazy var notificationManager: NotificationManager = {
        NotificationManager()
    }()
}

ส่วนประกอบ UI ในโค้ด

เมื่อสร้างอินเทอร์เฟซด้วยโปรแกรม (โดยไม่มี Storyboard) คุณสมบัติ lazy ช่วยให้จัดระเบียบการเริ่มต้นส่วนประกอบ UI โดยไม่ทำให้ init รก

ข้อจำกัดและข้อควรระวัง

ข้อจำกัดแรก: lazy ไม่สามารถใช้กับ let ได้ ค่าคงที่ต้องเริ่มต้นก่อนที่ init จะเสร็จสมบูรณ์ ซึ่งขัดแย้งกับแนวคิดของการเริ่มต้นแบบหน่วงเวลา

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

ข้อจำกัดที่สาม: คุณสมบัติ lazy ในโครงสร้างอาจทำให้เกิดปัญหาการเปลี่ยนแปลง หากโครงสร้างที่มีคุณสมบัติ lazy ถูกประกาศเป็น let การเข้าถึงคุณสมบัตินั้นเป็นไปไม่ได้เนื่องจากการเริ่มต้นต้องการการเปลี่ยนแปลงโครงสร้าง

ข้อจำกัดที่สี่: คุณสมบัติ lazy ไม่เรียก willSet/didSet ในระหว่างการเริ่มต้น เฉพาะในการเปลี่ยนแปลงครั้งต่อไป หากคุณสมบัติถูกประกาศเป็น var

ตาม Stack Overflow (2025) ประมาณ 15% ของคำถามเกี่ยวกับ lazy เกี่ยวข้องกับการพยายามใช้ lazy ในบริบท let หรือความเข้าใจผิดเกี่ยวกับการเริ่มต้นครั้งเดียว ข้อจำกัดเหล่านี้สำคัญที่ต้องพิจารณาเมื่อออกแบบคลาส

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

สามารถใช้ lazy กับ let ได้หรือไม่?

ไม่ได้ lazy พร้อมใช้งานเฉพาะ var เท่านั้น ค่าคงที่ที่ประกาศด้วย let ต้องเริ่มต้นก่อนที่ init จะเสร็จสมบูรณ์ ซึ่งไม่เข้ากันกับการเริ่มต้นแบบหน่วงเวลา

คุณสมบัติ lazy ถูกคำนวณกี่ครั้ง?

เพียงครั้งเดียว ในการเข้าถึงครั้งแรก คุณสมบัติจะเริ่มต้น หลังจากนั้นจะคืนค่าที่เก็บไว้โดยไม่คำนวณซ้ำ

คุณสมบัติ lazy ปลอดภัยในสภาพแวดล้อมหลายเธรดหรือไม่?

การเริ่มต้นปลอดภัยต่อเธรด — สองเธรดจะไม่เริ่มต้นคุณสมบัติสองครั้ง อย่างไรก็ตาม การเปลี่ยนแปลงในภายหลังจะไม่ถูกซิงโครไนซ์โดยอัตโนมัติ

สามารถแทนที่คุณสมบัติ lazy ในคลาสย่อยได้หรือไม่?

ไม่ได้ คุณสมบัติ lazy ไม่สามารถถูกแทนที่ได้ คลาสย่อยสามารถเปลี่ยนตรรกะภายในคลอเชอร์เท่านั้น แต่ไม่สามารถเปลี่ยนการเริ่มต้น lazy เองได้

lazy แตกต่างจากคุณสมบัติที่คำนวณอย่างไร?

Lazy คือคุณสมบัติที่เก็บข้อมูลซึ่งถูกคำนวณครั้งเดียวและเก็บค่าไว้ คุณสมบัติที่คำนวณจะถูกคำนวณทุกครั้งที่เข้าถึงและไม่เก็บค่า

สรุป

  • Lazy Property — กลไกการเริ่มต้นแบบหน่วงเวลาที่ดำเนินการในการเข้าถึงครั้งแรก
  • เฉพาะ var — lazy เข้ากันไม่ได้กับ let เพราะค่าคงที่ต้องการการเริ่มต้นทันที
  • ครั้งเดียว — การเริ่มต้นเกิดขึ้นครั้งเดียว การเข้าถึงครั้งต่อไปใช้ค่าที่แคชไว้
  • ความปลอดภัยของเธรด — การเริ่มต้นถูกซิงโครไนซ์ แต่การเปลี่ยนแปลงหลังเริ่มต้นต้องการการซิงโครไนซ์แยกต่างหาก
  • การใช้งาน — ทรัพยากรหนัก ส่วนประกอบ UI บริการ singleton การกำหนดค่า
  • ข้อจำกัด — ไม่สามารถใช้กับ let คุณสมบัติที่คำนวณ การแทนที่ หรือโครงสร้างที่มีอินสแตนซ์ let
  • การปรับให้เหมาะสม — ลดเวลาเริ่มต้นและการใช้หน่วยความจำสำหรับคุณสมบัติที่ใช้งานน้อย

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

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

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

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