موفّرو المخططات الزمنية واللقطات
وفّروا محتوى Widget بمرور الوقت
موفّرو المخططات الزمنية واللقطات درس مجاني في Swift Academy على CoddyKit. هذا هو الدرس 2 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في Swift Academy، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة Swift Academy 4 دروس في المجموع.
مهمة الموفّر
لا تحدّث الودجة نفسها باستمرار. بدلًا من ذلك، يزوّد TimelineProvider WidgetKit بجدول من الإدخالات المعروضة مسبقًا، ثم يعرض النظام كل إدخال في الوقت المناسب. ويجيب الموفّر عن ثلاثة أسئلة: العنصر النائب، واللقطة، والخط الزمني.
import WidgetKit
// TimelineProvider supplies:
// placeholder(in:) -> instant skeleton
// getSnapshot(in:) -> one entry for previews
// getTimeline(in:) -> future entries + refresh policyالالتزام بـ TimelineProvider
يلتزم الموفّر بـ TimelineProvider مع نوع Entry مرتبط. وتنفّذون الأساليب الثلاثة؛ إذ يزوّد كل منها بقيمة Context تصف العائلة وما إذا كان العرض معاينة.
import WidgetKit
struct WeatherProvider: TimelineProvider {
typealias Entry = WeatherEntry
func placeholder(in context: Context) -> WeatherEntry {
WeatherEntry(date: Date(),
temperature: 20, condition: "Sunny")
}
// getSnapshot and getTimeline follow
}العنصر النائب
يجب أن يعيد placeholder(in:) البيانات الوهمية التمثيلية فورًا. يعرضها النظام على شكل هيكل محجوب أثناء تحميل الودجة الحقيقية وفي معرض الودجات. لا تنفّذوا هنا أي عمليات على الشبكة أو القرص.
import WidgetKit
func placeholder(in context: Context) -> WeatherEntry {
// Synchronous, fake data, no I/O
WeatherEntry(date: Date(),
temperature: 0, condition: "--")
}اللقطة
يوفّر getSnapshot إدخالًا واحدًا للمواقف المؤقتة، مثل معاينة الودجة في المعرض. ويجب أن يعيده بسرعة. عندما تكون قيمة context.isPreview هي true، استخدموا بيانات نموذجية بدلًا من عملية جلب بطيئة حتى يظهر المعرض فورًا.
import WidgetKit
func getSnapshot(
in context: Context,
completion: @escaping (WeatherEntry) -> Void) {
if context.isPreview {
completion(WeatherEntry(date: Date(),
temperature: 22, condition: "Clear"))
} else {
completion(currentEntry())
}
}الخط الزمني
يمثّل getTimeline جوهر العملية: تنشئون مصفوفة من الإدخالات المستقبلية وتجمعونها مع سياسة إعادة التحميل في Timeline. يعرض النظام كل إدخال في تاريخه، ثم يطلب خطًا زمنيًا جديدًا وفقًا للسياسة.
import WidgetKit
func getTimeline(
in context: Context,
completion: @escaping (Timeline<WeatherEntry>) -> Void) {
let entries = buildEntries()
let timeline = Timeline(
entries: entries, policy: .atEnd)
completion(timeline)
}سياسات إعادة التحميل
تتحكم سياسة إعادة التحميل في وقت طلب WidgetKit للخط الزمني التالي: .atEnd بعد تاريخ الإدخال الأخير، أو .after(date) في وقت محدد، أو .never إلى أن تعيدوا التحميل يدويًا. ويضع النظام ميزانية لهذه العمليات، لذلك لا تتوقعوا تحديثات كل ثانية.
import WidgetKit
// .atEnd -> reload after final entry
// .after(someDate) -> reload at a chosen time
// .never -> only on manual reloadTimelines
let policy = TimelineReloadPolicy.atEnd
_ = policyإنشاء الإدخالات المستقبلية
من الأنماط الشائعة احتساب الساعات التالية مسبقًا، حتى تُحدَّث الودجة من دون إيقاظ التعليمات البرمجية في كل مرة. أنشئوا إدخالات على فواصل زمنية تبدأ من الوقت الحالي وتمتد إلى المستقبل، على أن يحتوي كل إدخال على بيانات تلك اللحظة.
import WidgetKit
import Foundation
func hourlyEntries() -> [WeatherEntry] {
var entries: [WeatherEntry] = []
let now = Date()
for hour in 0..<6 {
let date = Calendar.current.date(
byAdding: .hour, value: hour, to: now)!
entries.append(WeatherEntry(date: date,
temperature: 18 + hour, condition: "Sunny"))
}
return entries
}البيانات غير المتزامنة في الخط الزمني
إذا كان لا بد من الجلب من الشبكة، فنفّذوه قبل استدعاء completion. غلّفوا العمل غير المتزامن داخل Task، ولا تُكملوا التنفيذ إلا بعد وصول البيانات. احرصوا على السرعة، إذ إن الموفّرين يعملون ضمن مهلة زمنية ضيقة.
import WidgetKit
func getTimeline(
in context: Context,
completion: @escaping (Timeline<WeatherEntry>) -> Void) {
Task {
let entry = await fetchForecast()
let timeline = Timeline(
entries: [entry], policy: .after(
Date().addingTimeInterval(3600)))
completion(timeline)
}
}
func fetchForecast() async -> WeatherEntry {
WeatherEntry(date: Date(),
temperature: 21, condition: "Cloudy")
}الأهمية والميزانية
يحدّ WidgetKit من عدد مرات التحديث يوميًا لحماية البطارية. ولا يمكنكم فرض تحديثات متكررة. وفّروا عدة إدخالات في كل خط زمني، واختاروا وقت إعادة تحميل معقولًا؛ واستخدموا reloadTimelines من التطبيق فقط عند حدوث تغييرات مهمة في البيانات.
import WidgetKit
// The system, not you, decides exact refresh timing.
// Strategy: pre-bake multiple entries + a sensible policy
// + app-driven reloads on real changes.
let budget = "refreshes are budgeted by the OS"
_ = budgetموفّر الودجات القابلة للتهيئة
بالنسبة إلى ودجة AppIntentConfiguration، استخدموا AppIntentTimelineProvider بدلًا من ذلك. تستقبل أساليبه الـ intent الذي هيّأه المستخدم، ولذلك يمكنكم جلب البيانات للخيار المحدد، مثل المدينة أو الحساب المختار.
import WidgetKit
// AppIntentTimelineProvider adds the configuration:
// func timeline(for configuration: MyIntent,
// in context: Context)
// async -> Timeline<Entry>
let configurable = "intent-aware provider"
_ = configurableجمع أجزاء الموفّر
يوفّر الموفّر الكامل عنصرًا نائبًا فوريًا، ولقطة سريعة تراعي المعاينة، وخطًا زمنيًا من الإدخالات المُعدّة مسبقًا مع سياسة إعادة تحميل مناسبة، وبذلك تظل الودجة محدّثة ضمن الميزانية التي يحددها النظام.
import WidgetKit
// 1. placeholder -> instant dummy
// 2. getSnapshot -> sample when isPreview, else current
// 3. getTimeline -> [entries] + .atEnd or .after
let summary = "three methods, one current widget"
_ = summaryاختبار سريع
تذكّروا القيد المفروض على أسلوب العنصر النائب.
مراجعة
تعلّمتم موفّرات الخطوط الزمنية:
- يعيد
placeholderبيانات وهمية فورًا؛ ويعيدgetSnapshotإدخالًا واحدًا، مع استخدام بيانات نموذجية عندما تكون قيمةisPreviewصحيحة؛ ويعيدgetTimelineإدخالات مستقبلية مع سياسة. - سياسات إعادة التحميل هي
.atEndأو.after(date)أو.never؛ ويتولى نظام التشغيل تحديد ميزانية عمليات التحديث الفعلية. - جهّزوا إدخالات متعددة مسبقًا، ونفّذوا عمليات الجلب غير المتزامنة قبل إكمال التنفيذ.
- تستخدم الودجات القابلة للتهيئة
AppIntentTimelineProvider.
الأسئلة الشائعة
هل درس «موفّرو المخططات الزمنية واللقطات» مجاني؟
نعم — نص درس «موفّرو المخططات الزمنية واللقطات» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة Swift Academy، انتقل إلى CoddyKit PRO. تتضمن دورة Swift Academy 4 دروس في المجموع.
ماذا ستتعلم في «موفّرو المخططات الزمنية واللقطات»؟
وفّروا محتوى Widget بمرور الوقت تتمرن على Swift Academy مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.
هل أحتاج إلى خبرة سابقة لأبدأ Swift Academy؟
لا تُشترط خبرة سابقة. Swift Academy على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 2 من أصل 4.
كم من الوقت يستغرق درس «موفّرو المخططات الزمنية واللقطات»؟
معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.
هل يمكنني كتابة وتشغيل أكواد في درس Swift Academy هذا؟
نعم. كل درس في Swift Academy يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.
جميع الدروس في هذه الدورة
- إنشاء Widget باستخدام WidgetKit
- موفّرو المخططات الزمنية واللقطات
- نظرة عامة على امتدادات التطبيقات
- App Intents والاختصارات