WidgetKit فریمورک اپل است که در iOS 14 معرفی شد و به توسعهدهندگان امکان میدهد ویجتهای پویا را در صفحه اصلی iPhone و iPad، دسکتاپ Mac و صفحه Apple Watch قرار دهند. ویجتها اطلاعات کلیدی را بدون باز کردن برنامه نمایش میدهند — پیشبینی آبوهوا، نرخ ارز، تقویم، گامها. طبق Apple Developer Documentation, 2026، WidgetKit روزانه تا 2 میلیارد بهروزرسانی ویجت را در اکوسیستم اپل پردازش میکند که آن را به یکی از پراستفادهترین فریمورکها برای نمایش اطلاعات در صفحههای سیستمی تبدیل میکند.
نکات اصلی
WidgetKit فریمورک اپل برای ایجاد ویجتهایی است که محتوا را در صفحههای سیستمی دستگاههای اپل نمایش میدهند. ویجت نمایش مینیاتوری از برنامه شماست که کاربر در حالت «تکان دادن» (jiggle mode) در صفحه اصلی قرار میدهد. برخلاف کامپلیکیشنهای watchOS که قبل از WidgetKit وجود داشتند، فریمورک جدید ایجاد ویجتها را برای همه پلتفرمهای اپل از طریق یک API یکپارچه در SwiftUI یکپارچه کرد.
اصل کار WidgetKit بر اساس TimelineProvider است — شیئی که آرایهای مرتب از TimelineEntry ایجاد میکند که هر ورودی شامل Snapshot (وضعیت خاص ویجت در یک لحظه مشخص) است. سیستم ورودیها را به صورت متوالی نمایش میدهد و ویجت را هنگام انتقال به ورودی بعدی در خط زمانی بهروزرسانی میکند. بین ورودیها، WidgetKit کد برنامه را فراخوانی نمیکند — زمان پردازنده فقط هنگام ایجاد Timeline جدید مصرف میشود.
طبق دادههای WWDC 2024 Session «WidgetKit: What's new»، کاربر متوسط iOS 8–12 ویجت در صفحه اصلی خود دارد و محبوبترین دستهها آبوهوا، زمان، تقویم، تناسب اندام و امور مالی هستند. WidgetKit کمتر از 1% شارژ باتری در روز را در استفاده معمولی مصرف میکند زیرا بهروزرسانیها طبق برنامه انجام میشوند، نه در زمان واقعی.
قبل از iOS 14، ویجتها فقط به صورت Today View وجود داشتند — پنلی که با کشیدن به چپ از صفحه اول قابل دسترسی بود. Today Extension محدودیتهای جدی داشت: فقط در صفحه «امروز» در دسترس بود، برای بهروزرسانی محتوا نیاز به باز کردن برنامه داشت و پشتیبانی محدودی از اندازهها داشت. WidgetKit کاملاً جایگزین Today Extension شد و ویجتها را در صفحه اصلی، صفحه قفل (iOS 16+) و دسکتاپ Mac فراهم کرد.
معماری WidgetKit بر سه پروتکل کلیدی استوار است: TimelineProvider، TimelineEntry و Widget. TimelineEntry یک مدل داده است که وضعیت ویجت را در یک لحظه خاص نشان میدهد. TimelineProvider آرایهای از چنین ورودیهایی (Timeline) ایجاد میکند و تاریخ فعالسازی هرکدام را مشخص میکند. Widget نقطه ورودی است که ارائهدهنده را به نمای SwiftUI متصل میکند.
روش 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) تقریباً نیمی از صفحه را به صورت عمودی اشغال میکند و نمایش جداول، لیستها یا دادههای گسترده را امکانپذیر میسازد.
توسعهدهنده باید حداقل دو اندازه را پشتیبانی کند — اپل small + medium را توصیه میکند. ویجت Large فقط در صورتی لازم است که برنامه محتوای کافی برای پر کردن چنین حجمی داشته باشد. هر اندازه نمای SwiftUI مخصوص خود را دریافت میکند که 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 برای نمایش دادهها و پیکربندی ارائهدهنده برای زمانبندی صحیح بهروزرسانیهاست.
در زیر — مثال کاملی از یک ویجت ساده برای نمایش قیمت فعلی بیتکوین: 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 پشتیبانی از Lock Screen — صفحه قفل iPhone را گسترش داد. ویجتهای Lock Screen دو نوع هستند: inline (یک خط متن زیر ساعت) و rectangular (ناحیه مستطیلی). برخلاف ویجتهای Home Screen، ویجتهای Lock Screen بیشتر بهروزرسانی میشوند — محرک سیستمی امکان بهروزرسانی آنها را هر 15–30 دقیقه برای نمایش اطلاعات بهروز بدون باز کردن قفل گوشی فراهم میکند.
ویجتهای Lock Screen نیاز به پیکربندی جداگانه از طریق WidgetConfiguration با accessoryFamilies دارند: accessoryCircular، accessoryRectangular، accessoryInline. این خانوادهها محدودیتهای دقیقی در اندازه و محتوا دارند — آنها از تصاویر، انیمیشن و فونتهای سفارشی پشتیبانی نمیکنند. اپل توصیه میکند برای ویجتهای Lock Screen فقط از اطلاعات متنی و آیکونهای سیستمی SF Symbols استفاده کنید.
در توسعه ویجتها مهم است که محدودیتهای WidgetKit را در نظر بگیرید. ویجتها نماهای فقط خواندنی هستند: آنها رویدادهای لمسی را پردازش نمیکنند (به جز لمس که برنامه را باز میکند). ویجتها از انیمیشن، ویدئو، ورودی صفحهکلید، اسکرول یا عناصر تعاملی پشتیبانی نمیکنند. هر ویجت یک عکس فوری ایستا از دادهها در یک لحظه خاص است و تلاش برای افزودن تعامل منجر به رد برنامه در App Store میشود.
بهترین روشها شامل Widget Center برای بهروزرسانی اجباری، ذخیرهسازی دادهها در سطح TimelineProvider برای پاسخ سریع و استفاده از placeholder برای حالت اولیه است. همچنین پشتیبانی از چندین اندازه مهم است — کاربر انتظار دارد که ویجت هم در نسخه small و هم medium در دسترس باشد. از نمایش دادههای نادقیق یا قدیمی خودداری کنید — کاربر اطلاعات نادرست را از ویجت برای مدت طولانی به خاطر میسپارد.
| غیرمجاز | دلیل |
|---|---|
| انیمیشن و ویدئو | ویجتها عکسهای فوری ایستا هستند; انیمیشن باتری را خالی میکند |
| تعامل | WidgetKit از عناصر UI غیر از لینک به برنامه پشتیبانی نمیکند |
| اسکرول | اندازه ثابت بدون اسکرول |
| صفحهکلید | ورود متن در ویجت غیرممکن است |
| دادههای زنده | دادهها طبق برنامه Timeline بهروزرسانی میشوند، نه در زمان واقعی |
| اندازههای سفارشی | فقط small, medium, large, accessory* ثابت |
سوالات متداول
بله، WidgetKit چند پلتفرمی است. همان Widget Extension میتواند با کد یکسان SwiftUI در اهداف iOS، iPadOS و macOS گنجانده شود. تفاوتها فقط در Familyهای پشتیبانی شده ظاهر میشود — در Mac accessoryRectangular وجود ندارد.
طبق برنامه Timeline. توسعهدهنده تعیین میکند که بهروزرسانی بعدی چه زمانی باشد — یک دقیقه یا یک روز بعد. سیستم همچنین میتواند بهروزرسانیها را برای ویجتهای پراستفاده تسریع کند.
خیر، WidgetKit از UIButton یا هر عنصر تعاملی پشتیبانی نمیکند. تنها عمل — لمس ویجت است که برنامه را از طریق deep link باز میکند.
از WidgetCenter.shared.reloadAllTimelines() یا reloadTimelines(ofKind:) برای ویجت خاص استفاده کنید. فراخوانی از برنامه بلافاصله Timeline جدیدی از ارائهدهنده درخواست میکند.
حداقل — کمتر از 1% شارژ در روز در استفاده معمولی. WidgetKit بهروزرسانیهای پسزمینه را محدود میکند و برنامه را فعال نگه نمیدارد. هزینه اصلی ایجاد Timeline در اولین افزودن است.
خلاصه
ما یک اپلیکیشن موبایل به صورت کلید در دست توسعه خواهیم داد
IT Sectr از سال 2017 برنامههای iOS و Android را برای استارتاپها و کسبوکارها ایجاد میکند. ما به شما مشاوره میدهیم و بهترین راهحل را پیشنهاد خواهیم کرد.
همچنین بخوانید