WidgetKit คือเฟรมเวิร์กของ Apple ที่เปิดตัวใน iOS 14 ซึ่งช่วยให้นักพัฒนาสามารถวางวิดเจ็ตแบบไดนามิกบนหน้าจอหลักของ iPhone และ iPad เดสก์ท็อป Mac และหน้าปัด Apple Watch วิดเจ็ตแสดงข้อมูลสำคัญโดยไม่ต้องเปิดแอป — พยากรณ์อากาศ อัตราแลกเปลี่ยน ปฏิทิน จำนวนก้าว ตามข้อมูลจาก Apple Developer Documentation, 2026 WidgetKit ประมวลผลการอัปเดตวิดเจ็ตมากถึง 2 พันล้านครั้งต่อวันในระบบนิเวศของ Apple ทำให้เป็นหนึ่งในเฟรมเวิร์กที่ใช้มากที่สุดสำหรับการแสดงข้อมูลบนหน้าจอระบบ
ประเด็นสำคัญ
WidgetKit คือเฟรมเวิร์กของ Apple สำหรับสร้างวิดเจ็ตที่แสดงเนื้อหาบนหน้าจอระบบของอุปกรณ์ Apple วิดเจ็ตคือการแสดงขนาดเล็กของแอปของคุณที่ผู้ใช้วางบนหน้าจอหลักในโหมด jiggle ต่างจากคอมพลิเคชัน watchOS ที่มีอยู่ก่อน WidgetKit เฟรมเวิร์กใหม่ได้รวมการสร้างวิดเจ็ตสำหรับทุกแพลตฟอร์ม Apple ผ่าน API SwiftUI เดียว
หลักการทำงานของ WidgetKit ขึ้นอยู่กับ TimelineProvider — ออบเจกต์ที่สร้างอาร์เรย์ลำดับของ TimelineEntry ซึ่งแต่ละรายการมี Snapshot (สถานะเฉพาะของวิดเจ็ต ณ เวลาที่กำหนด) ระบบจะแสดงรายการตามลำดับ อัปเดตวิดเจ็ตเมื่อย้ายไปยังรายการถัดไปบนไทม์ไลน์ ระหว่างรายการ WidgetKit จะไม่เรียกใช้โค้ดแอป — เวลา CPU จะใช้เฉพาะเมื่อสร้าง Timeline ใหม่เท่านั้น
ตาม เซสชัน WWDC 2024 “WidgetKit: What’s new” ผู้ใช้ iOS โดยเฉลี่ยมีวิดเจ็ต 8–12 รายการบนหน้าจอหลัก และหมวดหมู่ยอดนิยมที่สุดคือสภาพอากาศ เวลา ปฏิทิน ฟิตเนส และการเงิน WidgetKit ใช้พลังงานแบตเตอรี่น้อยกว่า 1% ต่อวันในการใช้งานทั่วไป ต้องขอบคุณการอัปเดตตามกำหนดการแทนที่จะเป็นแบบเรียลไทม์
ก่อน iOS 14 วิดเจ็ตมีอยู่เฉพาะในรูปแบบ Today View — แผงที่เข้าถึงได้โดยการปัดไปทางซ้ายจากหน้าจอแรก Today Extensions มีข้อจำกัดที่ร้ายแรง: ใช้ได้เฉพาะบนหน้าจอ “วันนี้” ต้องเปิดแอปเพื่ออัปเดตเนื้อหา และรองรับขนาดที่จำกัด WidgetKit ได้แทนที่ Today Extensions อย่างสมบูรณ์ โดยให้วิดเจ็ตบนหน้าจอหลัก หน้าจอล็อก (iOS 16+) และเดสก์ท็อป Mac
สถาปัตยกรรม WidgetKit สร้างขึ้นบนโปรโตคอลหลักสามตัว: TimelineProvider, TimelineEntry และ Widget TimelineEntry คือโมเดลข้อมูลที่แสดงสถานะของวิดเจ็ต ณ เวลาใดเวลาหนึ่ง TimelineProvider สร้างอาร์เรย์ของรายการดังกล่าว (Timeline) โดยระบุวันที่เปิดใช้งานสำหรับแต่ละรายการ Widget คือจุดเริ่มต้นที่เชื่อมต่อผู้ให้บริการกับมุมมอง SwiftUI
เมธอด Timeline getTimeline ถูกเรียกโดยระบบเมื่อเพิ่มวิดเจ็ตครั้งแรก และจากนั้นเป็นระยะ — โดยปกติทุกๆ 1–6 ชั่วโมง ขึ้นอยู่กับประเภทของผู้ให้บริการ Timeline สามารถมีรายการสำหรับชั่วโมงหรือวันข้างหน้า ทำให้วิดเจ็ตทำงานได้โดยไม่ต้องเรียกใช้โค้ดแอประหว่างการอัปเดต หากจำเป็นต้องอัปเดตวิดเจ็ตอย่างเร่งด่วน (เช่น อัตราแลกเปลี่ยนเปลี่ยนแปลง) แอปสามารถเรียก WidgetCenter.shared.reloadAllTimelines() แบบบังคับได้
struct SimpleEntry: TimelineEntry {
let date: Date
let value: Double
}
struct Provider: TimelineProvider {
typealias Entry = SimpleEntry
func placeholder(in context: Context) -> Entry {
Entry(date: Date(), value: 0)
}
func getSnapshot(
in context: Context,
completion: @escaping (Entry) -> Void
) {
Entry(date: Date(), value: 42.5)
}
func getTimeline(
in context: Context,
completion: @escaping (Timeline<Entry>, Error?) -> Void
) {
let entry = Entry(date: Date(), value: fetchLatestValue())
let nextUpdate = Calendar.current
.date(byAdding: .hour, value: 1, to: Date())!
let timeline = Timeline(entries: [entry], policy: .after(nextUpdate))
completion(timeline, nil)
}
}
WidgetKit รองรับสามขนาดวิดเจ็ต แต่ละขนาดมีสัดส่วนคงที่ Small (170×170 pt บน iPhone) แสดงข้อมูลขนาดกะทัดรัด — ค่าเดียว ไอคอน หรือข้อความสั้น Medium (364×170 pt) กว้างเป็นสองเท่าของ small และเหมาะสำหรับการแสดงค่าคู่หรือแผนภูมิขนาดเล็ก Large (364×382 pt) ครอบครองเกือบครึ่งหน้าจอในแนวตั้ง และสามารถแสดงตาราง รายการ หรือข้อมูลแบบขยายได้
นักพัฒนาต้องรองรับอย่างน้อยสองขนาด — Apple แนะนำ small + medium วิดเจ็ต Large จำเป็นเฉพาะเมื่อแอปมีเนื้อหาเพียงพอที่จะเติมเต็มปริมาณดังกล่าว แต่ละขนาดจะได้รับ SwiftUI View ของตัวเอง ซึ่ง WidgetKit จะเรนเดอร์บนหน้าจอระบบ สิ่งสำคัญคือ WidgetKit ไม่รองรับขนาดที่กำหนดเอง — มีเพียงสามขนาดคงที่ ซึ่งรับประกันความสอดคล้องของอินเทอร์เฟซ
struct WeatherWidget: Widget {
let kind: String = "WeatherWidget"
var body: some WidgetConfiguration {
StaticConfiguration(kind: kind, provider: Provider()) { entry in
WeatherWidgetView(entry: entry)
}
.configurationDisplayName("Weather")
.description("Current temperature and forecast")
.supportedFamilies([.systemSmall, .systemMedium])
}
}
WidgetKit เสนอสองประเภทการกำหนดค่า — StaticConfiguration และ IntentConfiguration StaticConfiguration เหมาะสำหรับวิดเจ็ตที่แสดงเนื้อหาเดียวกันสำหรับผู้ใช้ทุกคน: อัตราแลกเปลี่ยน สภาพอากาศ ปฏิทิน IntentConfiguration อนุญาตให้ผู้ใช้ปรับแต่งวิดเจ็ตเมื่อเพิ่มผ่านระบบอินเทนต์ของ Siri — ตัวอย่างเช่น เลือกเมืองเฉพาะสำหรับสภาพอากาศ หรือหลักทรัพย์เฉพาะสำหรับราคาหุ้น
IntentConfiguration ใช้ INWidgetIntent — คลาสย่อยของ INIntent จาก SiriKit เมื่อผู้ใช้เพิ่มวิดเจ็ตและเลือกพารามิเตอร์ (เช่น เมือง) ระบบจะบันทึกอินเทนต์นี้และส่งต่อไปยัง TimelineProvider ในการอัปเดตแต่ละครั้ง ผู้ให้บริการได้รับอินเทนต์ในเมธอด getTimeline และใช้พารามิเตอร์ของมันเพื่อสร้างเนื้อหา IntentConfiguration เป็นวิธีที่ต้องการสำหรับวิดเจ็ตส่วนบุคคล เนื่องจากรวมเข้ากับ Siri และ Shortcuts
struct WeatherWidgetEntryView: View {
var entry: WeatherEntry
var body: some View {
VStack(alignment: .leading) {
Text(entry.cityName)
.font(.caption)
.foregroundColor(.secondary)
Text("\(entry.temperature)°C")
.font(.largeTitle)
}
}
}
struct WeatherWidget: Widget {
var body: some WidgetConfiguration {
IntentConfiguration(
kind: "WeatherWidget",
intent: WeatherConfigIntent.self,
provider: WeatherTimelineProvider()
) { entry in
WeatherWidgetEntryView(entry: entry)
}
}
}
การสร้างวิดเจ็ตเริ่มต้นด้วยการเพิ่ม Widget Extension Target ใน Xcode: File → New → Target → Widget Extension Xcode จะสร้างโครงสร้างที่มี TimelineEntry, TimelineProvider และ WidgetConfiguration โดยอัตโนมัติ นักพัฒนาเพียงแค่ต้องใช้ SwiftUI View เพื่อแสดงข้อมูลและกำหนดค่าผู้ให้บริการสำหรับตารางการอัปเดตที่ถูกต้อง
ด้านล่างนี้คือตัวอย่างที่สมบูรณ์ของวิดเจ็ตอย่างง่ายสำหรับแสดงราคา Bitcoin ปัจจุบัน: Provider โหลดอัตราผ่าน URLSession และสร้าง Timeline ด้วยการอัปเดตทุกชั่วโมง WidgetSwiftUIView แสดงอัตราด้วยแบบอักษรขนาดใหญ่และเวลาอัปเดตล่าสุดด้วยแบบอักษรขนาดเล็ก
struct BTCPriceEntry: TimelineEntry {
let date: Date
let price: Double
let change24h: Double
}
struct BTCWidgetEntryView: View {
var entry: BTCPriceEntry
var body: some View {
VStack {
Text("BTC/USD").font(.caption)
Text("$\(entry.price, specifier: "%.0f")")
.font(.title2).fontWeight(.bold)
Text(entry.change24h > 0 ? "+" : "")
}
}
}
ด้วย iOS 16 WidgetKit ได้ขยายการรองรับไปยัง หน้าจอล็อก — หน้าจอล็อกของ iPhone วิดเจ็ตหน้าจอล็อกมีสองประเภท: inline (ข้อความหนึ่งบรรทัดใต้นาฬิกา) และ rectangular (พื้นที่สี่เหลี่ยม) ต่างจากวิดเจ็ตหน้าจอหลัก วิดเจ็ตหน้าจอล็อกอัปเดตบ่อยกว่า — ทริกเกอร์ของระบบอนุญาตให้อัปเดตทุก 15–30 นาทีเพื่อแสดงข้อมูลปัจจุบันโดยไม่ต้องปลดล็อกโทรศัพท์
วิดเจ็ตหน้าจอล็อกต้องการการกำหนดค่าแยกต่างหากผ่าน WidgetConfiguration ด้วย accessoryFamilies: accessoryCircular, accessoryRectangular, accessoryInline ตระกูลเหล่านี้มีข้อจำกัดด้านขนาดและเนื้อหาที่เข้มงวด — ไม่รองรับรูปภาพ ภาพเคลื่อนไหว หรือแบบอักษรที่กำหนดเอง Apple แนะนำให้ใช้เฉพาะข้อมูลข้อความและไอคอนระบบ SF Symbols สำหรับวิดเจ็ตหน้าจอล็อก
เมื่อพัฒนาวิดเจ็ต สิ่งสำคัญคือต้องพิจารณาข้อจำกัดของ WidgetKit วิดเจ็ตเป็นมุมมองแบบอ่านอย่างเดียว: ไม่จัดการกับเหตุการณ์สัมผัส (ยกเว้นการแตะที่เปิดแอป) วิดเจ็ตไม่รองรับภาพเคลื่อนไหว วิดีโอ การป้อนข้อมูลจากแป้นพิมพ์ การเลื่อน หรือองค์ประกอบเชิงโต้ตอบ วิดเจ็ตแต่ละตัวเป็นภาพนิ่งของข้อมูล ณ เวลาที่กำหนด และการพยายามเพิ่มการโต้ตอบจะส่งผลให้แอปถูกปฏิเสธจาก App Store
แนวทางปฏิบัติที่ดีที่สุดรวมถึงการใช้ Widget Center สำหรับการอัปเดตแบบบังคับ การแคชข้อมูลในระดับ TimelineProvider เพื่อการตอบสนองที่รวดเร็ว และการใช้ตัวยึดตำแหน่งสำหรับสถานะเริ่มต้น นอกจากนี้ยังสำคัญที่จะรองรับหลายขนาด — ผู้ใช้คาดหวังว่าวิดเจ็ตจะพร้อมใช้งานทั้งในรูปแบบ small และ medium หลีกเลี่ยงการแสดงข้อมูลที่ไม่ถูกต้องหรือล้าสมัยอย่างเคร่งครัด — ผู้ใช้จดจำข้อมูลที่ไม่ถูกต้องจากวิดเจ็ตได้เป็นเวลานาน
| สิ่งที่ไม่ได้รับอนุญาต | เพราะเหตุใด |
|---|---|
| ภาพเคลื่อนไหวและวิดีโอ | วิดเจ็ตเป็นภาพนิ่ง; ภาพเคลื่อนไหวทำให้แบตเตอรี่หมด |
| การโต้ตอบ | WidgetKit ไม่รองรับองค์ประกอบ UI ยกเว้นลิงก์แอป |
| การเลื่อน | ขนาดคงที่ไม่มีการเลื่อน |
| แป้นพิมพ์ | ไม่สามารถป้อนข้อความในวิดเจ็ตได้ |
| ข้อมูลสด | ข้อมูลอัปเดตตามกำหนดการ Timeline ไม่ใช่แบบเรียลไทม์ |
| ขนาดที่กำหนดเอง | เฉพาะขนาดคงที่ small, medium, large, accessory* |
คำถามที่พบบ่อย
ได้ WidgetKit รองรับหลายแพลตฟอร์ม Widget Extension เดียวกันสามารถรวมอยู่ในเป้าหมาย iOS, iPadOS และ macOS ด้วยโค้ด SwiftUI เดียวกัน ความแตกต่างจะปรากฏเฉพาะในตระกูลที่รองรับ — Mac ไม่มี accessoryRectangular
ตามกำหนดการ Timeline นักพัฒนากำหนดว่าการอัปเดตครั้งต่อไปจะเกิดขึ้นเมื่อใด — ในหนึ่งนาทีหรือหนึ่งวัน ระบบยังสามารถเร่งการอัปเดตสำหรับวิดเจ็ตที่ใช้บ่อยได้
ไม่ WidgetKit ไม่รองรับ UIButton หรือองค์ประกอบเชิงโต้ตอบใดๆ การกระทำเดียวคือการแตะที่วิดเจ็ต ซึ่งจะเปิดแอปผ่าน deep link
ใช้ WidgetCenter.shared.reloadAllTimelines() หรือ reloadTimelines(ofKind:) สำหรับวิดเจ็ตเฉพาะ การเรียกจากแอปจะขอ Timeline ใหม่จากผู้ให้บริการทันที
น้อยมาก — น้อยกว่า 1% ของแบตเตอรี่ต่อวันในการใช้งานทั่วไป WidgetKit จำกัดการอัปเดตในพื้นหลังและไม่ทำให้แอปทำงานอยู่ตลอด การใช้พลังงานหลักคือการสร้าง Timeline เมื่อเพิ่มครั้งแรก
สรุป
เราจะพัฒนาแอปพลิเคชันบนมือถือแบบครบวงจร
IT Sectr สร้างแอปพลิเคชัน iOS และ Android สำหรับสตาร์ทอัพและธุรกิจตั้งแต่ปี 2017 เราจะให้คำแนะนำและเสนอวิธีแก้ปัญหาที่ดีที่สุดแก่คุณ