Section 6/141 menit
6. Timeline Provider Lanjutan
6. Timeline Provider Lanjutan
Async TimelineProvider
Untuk network request, gunakan AppIntentTimelineProvider (iOS 17+) atau TimelineProvider dengan completion-based async:
swift
struct NewsProvider: TimelineProvider {
func getTimeline(in context: Context, completion: @escaping (Timeline<NewsEntry>) -> Void) {
Task {
do {
let articles = try await NewsAPI.fetchLatest()
var entries: [NewsEntry] = []
let now = Date()
// Buat satu entry per jam untuk 6 jam ke depan
for hourOffset in 0..<6 {
let entryDate = Calendar.current.date(
byAdding: .hour,
value: hourOffset,
to: now
) ?? now
// Tampilkan artikel berbeda di tiap jam
let article = articles[hourOffset % articles.count]
entries.append(NewsEntry(date: entryDate, article: article))
}
let timeline = Timeline(entries: entries, policy: .atEnd)
completion(timeline)
} catch {
// Fallback jika network error
let fallback = NewsEntry(date: Date(), article: .placeholder)
let timeline = Timeline(entries: [fallback], policy: .after(Date().addingTimeInterval(3600)))
completion(timeline)
}
}
}
}
Refresh Manual dari App
swift
// Di app utama — panggil setelah data berubah
import WidgetKit
func userCompletedHabit() {
saveHabitDataToSharedDefaults()
// Reload hanya widget tertentu
WidgetCenter.shared.reloadTimelines(ofKind: "HabitWidget")
// Atau reload semua widget
WidgetCenter.shared.reloadAllTimelines()
}
Relevant dan Kontekstual (iOS 16+)
swift
// Beri tahu sistem kapan widget paling relevan untuk ditampilkan di Smart Stack
struct SmartHabitProvider: TimelineProvider {
func getTimeline(in context: Context, completion: @escaping (Timeline<HabitEntry>) -> Void) {
var entries: [HabitEntry] = []
// Entry pagi — widget paling relevan saat pengguna biasanya olahraga
let morningDate = Calendar.current.date(
bySettingHour: 7, minute: 0, second: 0, of: Date()
) ?? Date()
let morningEntry = HabitEntry(date: morningDate, habitName: "Olahraga", isCompleted: false, streak: 5)
entries.append(morningEntry)
let timeline = Timeline(entries: entries, policy: .atEnd)
completion(timeline)
}
}