Lazy Property ใน Swift เป็นกลไกการเริ่มต้นแบบหน่วงเวลา โดยคุณสมบัติจะถูกคำนวณ ณ เวลาที่มีการเข้าถึงครั้งแรก แทนที่จะเป็นตอนที่สร้างอ็อบเจกต์ แตกต่างจากคุณสมบัติที่เก็บข้อมูลทั่วไป ตัวแปร lazy สามารถลดเวลาเริ่มต้นและการใช้หน่วยความจำสำหรับการดำเนินงานที่ใช้ทรัพยากรมากได้อย่างมีนัยสำคัญ ตามเอกสารของนักพัฒนา Apple (2026) คุณสมบัติ lazy รับประกันว่าจะเริ่มต้นเพียงครั้งเดียวและปลอดภัยต่อเธรดในการเข้าถึงครั้งแรก
ประเด็นสำคัญ
Lazy Property คือคุณสมบัติที่เก็บข้อมูลซึ่งการเริ่มต้นถูกหน่วงเวลาจนกว่าจะมีการเข้าถึงครั้งแรก คำสำคัญ lazy ก่อนการประกาศ var บอกให้คอมไพเลอร์ไม่คำนวณค่าเมื่อสร้างอ็อบเจกต์
ในกรณีมาตรฐาน คุณสมบัติที่เก็บข้อมูลทั้งหมดจะเริ่มต้นเมื่อสร้างอินสแตนซ์ของคลาสหรือโครงสร้าง หากคุณสมบัติต้องการการคำนวณที่ซับซ้อน การโหลดจากเครือข่าย หรือการดำเนินการกับระบบไฟล์ lazy อนุญาตให้ หน่วงเวลา การดำเนินการนี้จนกว่าจะจำเป็นต้องใช้ข้อมูลจริงๆ
ตาม Swift by Sundell (2025) คุณสมบัติ lazy เป็นหนึ่งในเครื่องมือปรับประสิทธิภาพที่มีประสิทธิภาพมากที่สุดในแอปพลิเคชัน iOS สามารถ ลด เวลาเริ่มต้นลง 20–40% ในแอปที่มีการตั้งค่าเริ่มต้นหนัก เช่น โปรแกรมแก้ไขกราฟิกหรือแดชบอร์ดวิเคราะห์
การประกาศคุณสมบัติ lazy ต้องใช้คำสำคัญ lazy ก่อน var ค่าถูกกำหนดผ่านคลอเชอร์หรือการเรียกใช้ฟังก์ชัน
class DataManager {
lazy var dataLoader: DataLoader = DataLoader()
lazy var config: Configuration = {
let config = Configuration()
config.loadDefaults()
return config
}()
}
คลอเชอร์ สำหรับคุณสมบัติ lazy จะถูกคำนวณเพียงครั้งเดียวและคืนค่าที่เก็บไว้ในการเข้าถึงครั้งต่อไป สะดวกเป็นพิเศษสำหรับการกำหนดค่าที่ซับซ้อนที่มีหลายขั้นตอน
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 และคุณสมบัติที่เก็บข้อมูลทั่วไป การเริ่มต้นเกิดขึ้นเมื่อมีการอ่านหรือเขียนคุณสมบัติครั้งแรก แต่ไม่ก่อนหน้านั้น
การเริ่มต้นจะถูกเรียกใช้ในการเข้าถึงคุณสมบัติครั้งแรก ไม่ว่าจะเป็นการอ่านหรือเขียน จนถึงช่วงเวลานั้น หน่วยความจำจะไม่ถูกจัดสรรสำหรับคุณสมบัติ — จะเก็บเพียงแฟล็ก “ยังไม่ได้เริ่มต้น” เท่านั้น
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 ปลอดภัยต่อเธรดใน Swift: หากสองเธรดเข้าถึงคุณสมบัติ lazy พร้อมกัน การเริ่มต้นจะเกิดขึ้นเพียงครั้งเดียว และเธรดที่สองจะถูกบล็อกจนกว่าจะเสร็จสมบูรณ์
อย่างไรก็ตาม การซิงโครไนซ์จะถูกยกเลิกหลังจากการเริ่มต้น ซึ่งหมายความว่าการอ่านพร้อมกันจากหลายเธรดปลอดภัย แต่หากเธรดหนึ่งเขียนค่าใหม่ลงใน lazy var ในขณะที่อีกเธรดอ่าน จะเกิด การแข่งข้อมูล
ตามข้อเสนอ Swift Evolution SE-0254 (2025) กลไกการซิงโครไนซ์สำหรับคุณสมบัติ lazy ถูกนำไปใช้ผ่าน objc_sync_enter/exit ในระดับต่ำ สิ่งนี้รับประกันการเริ่มต้นแบบอะตอมมิก แต่ไม่รับประกันการเปลี่ยนแปลงในภายหลัง สำหรับการทำงานที่ ปลอดภัยต่อเธรดกับคุณสมบัติ lazy ที่เปลี่ยนแปลงได้ ให้ใช้กลไกการซิงโครไนซ์แยกต่างหาก
คุณสมบัติ lazy ถูกใช้ในโปรเจกต์ Swift เพื่อเพิ่มประสิทธิภาพและปรับปรุงสถาปัตยกรรมโค้ด
การโหลดรูปภาพ การแยกวิเคราะห์ JSON การทำงานกับฐานข้อมูล — การดำเนินการทั้งหมดนี้สามารถหน่วงเวลาโดยใช้ lazy จนกว่าผู้ใช้ต้องการข้อมูลจริงๆ
class ProfileViewController {
lazy var avatarImageView: UIImageView = {
let imageView = UIImageView()
imageView.contentMode = .scaleAspectFill
imageView.clipsToBounds = true
return imageView
}()
}
บริการ และตัวจัดการที่ไม่จำเป็นทันทีเมื่อเริ่มต้นแอป ประกาศเป็น lazy ได้อย่างมีประสิทธิภาพ ซึ่งช่วยลดเวลาเริ่มต้นและการใช้หน่วยความจำ
class AppDelegate {
lazy var analyticsService: AnalyticsService = {
let service = AnalyticsService()
service.configure()
return service
}()
lazy var notificationManager: NotificationManager = {
NotificationManager()
}()
}
เมื่อสร้างอินเทอร์เฟซด้วยโปรแกรม (โดยไม่มี Storyboard) คุณสมบัติ lazy ช่วยให้จัดระเบียบการเริ่มต้นส่วนประกอบ UI โดยไม่ทำให้ init รก
ข้อจำกัดแรก: lazy ไม่สามารถใช้กับ let ได้ ค่าคงที่ต้องเริ่มต้นก่อนที่ init จะเสร็จสมบูรณ์ ซึ่งขัดแย้งกับแนวคิดของการเริ่มต้นแบบหน่วงเวลา
ข้อจำกัดที่สอง: lazy ไม่พร้อมใช้งานสำหรับคุณสมบัติที่คำนวณ คุณสมบัติที่คำนวณไม่เก็บค่า ในขณะที่ lazy เป็นคุณสมบัติที่เก็บข้อมูลที่มีการเริ่มต้นแบบหน่วงเวลา
ข้อจำกัดที่สาม: คุณสมบัติ lazy ในโครงสร้างอาจทำให้เกิดปัญหาการเปลี่ยนแปลง หากโครงสร้างที่มีคุณสมบัติ lazy ถูกประกาศเป็น let การเข้าถึงคุณสมบัตินั้นเป็นไปไม่ได้เนื่องจากการเริ่มต้นต้องการการเปลี่ยนแปลงโครงสร้าง
ข้อจำกัดที่สี่: คุณสมบัติ lazy ไม่เรียก willSet/didSet ในระหว่างการเริ่มต้น เฉพาะในการเปลี่ยนแปลงครั้งต่อไป หากคุณสมบัติถูกประกาศเป็น var
ตาม Stack Overflow (2025) ประมาณ 15% ของคำถามเกี่ยวกับ lazy เกี่ยวข้องกับการพยายามใช้ lazy ในบริบท let หรือความเข้าใจผิดเกี่ยวกับการเริ่มต้นครั้งเดียว ข้อจำกัดเหล่านี้สำคัญที่ต้องพิจารณาเมื่อออกแบบคลาส
คำถามที่พบบ่อย
ไม่ได้ lazy พร้อมใช้งานเฉพาะ var เท่านั้น ค่าคงที่ที่ประกาศด้วย let ต้องเริ่มต้นก่อนที่ init จะเสร็จสมบูรณ์ ซึ่งไม่เข้ากันกับการเริ่มต้นแบบหน่วงเวลา
เพียงครั้งเดียว ในการเข้าถึงครั้งแรก คุณสมบัติจะเริ่มต้น หลังจากนั้นจะคืนค่าที่เก็บไว้โดยไม่คำนวณซ้ำ
การเริ่มต้นปลอดภัยต่อเธรด — สองเธรดจะไม่เริ่มต้นคุณสมบัติสองครั้ง อย่างไรก็ตาม การเปลี่ยนแปลงในภายหลังจะไม่ถูกซิงโครไนซ์โดยอัตโนมัติ
ไม่ได้ คุณสมบัติ lazy ไม่สามารถถูกแทนที่ได้ คลาสย่อยสามารถเปลี่ยนตรรกะภายในคลอเชอร์เท่านั้น แต่ไม่สามารถเปลี่ยนการเริ่มต้น lazy เองได้
Lazy คือคุณสมบัติที่เก็บข้อมูลซึ่งถูกคำนวณครั้งเดียวและเก็บค่าไว้ คุณสมบัติที่คำนวณจะถูกคำนวณทุกครั้งที่เข้าถึงและไม่เก็บค่า
สรุป
เราจะพัฒนาแอปพลิเคชันบนมือถือแบบครบวงจร
IT Sectr สร้างแอปพลิเคชัน iOS และ Android สำหรับสตาร์ทอัพและธุรกิจตั้งแต่ปี 2017 เราจะให้คำแนะนำและเสนอวิธีแก้ปัญหาที่ดีที่สุดแก่คุณ
อ่านเพิ่มเติม