I'm currently developing an application using SwiftUI.
I'm trying to develop a timer App
using Core Data
and iOS 14 Widget
.
I want to display 00:00
when the value of duration in Core Data
is 0.0
in the widget.
So I refer to this article SwiftUI iOS 14 Widget CountDown.
In this article, I have to use data fetched from Core Data in struct Provider: TimelineProvider
.
But When I declare a variable using @FetchRequest
in struct Provider: TimelineProvider
the data from Core Data never display. (// Display_A
in the code I attached bellow)
In the case of using @FetchRequest
in struct TimerWidgetEntryView : View
the data display well. (// Display_B
in the code I attached bellow)
This is a screenshot of my widget
My goal is to display 20.0
in both Display_A
and Display_B
in my code.
How could I do that?
Here is the code:
import WidgetKit
import SwiftUI
import CoreData
struct Provider: TimelineProvider {
var moc = PersistenceController.shared.managedObjectContext
init(context : NSManagedObjectContext) {
self.moc = context
}
@FetchRequest(entity: TimerEntity.entity(), sortDescriptors: [NSSortDescriptor(
key:"createdDate",ascending:true)],animation:.spring()) var timerEntity:FetchedResults<TimerEntity>
func placeholder(in context: Context) -> SimpleEntry {
return SimpleEntry(date: Date(), duration: timerEntity.first?.duration ?? 0.0)
}
func getSnapshot(in context: Context, completion: @escaping (SimpleEntry) -> ()) {
let entry = SimpleEntry(date: Date(), duration: timerEntity.first?.duration ?? 0.0)
return completion(entry)
}
func getTimeline(in context: Context, completion: @escaping (Timeline<Entry>) -> ()) {
var entries: [SimpleEntry] = []
let currentDate = Date()
for hourOffset in 0 ..< 5 {
let entryDate = Calendar.current.date(byAdding: .minute, value: hourOffset, to: currentDate)!
let entry = SimpleEntry(date: entryDate, duration: timerEntity.first?.duration ?? 0.0)
entries.append(entry)
}
let timeline = Timeline(entries: entries, policy: .atEnd)
completion(timeline)
}
}
struct SimpleEntry: TimelineEntry {
let date: Date
let duration: Double
}
struct TimerWidgetEntryView : View {
@FetchRequest(entity: TimerEntity.entity(), sortDescriptors: [NSSortDescriptor(
key:"createdDate",ascending:true)],animation:.spring()) var timerEntity:FetchedResults<TimerEntity>
var entry: Provider.Entry
var body: some View {
return (
VStack{
Text(String(entry.duration)) // Display_A
Text(String(timerEntity.first?.duration ?? 0.0)) // Display_B
}
)
}
}
@main
struct TimerWidget: Widget {
let kind: String = "TimerWidget"
var body: some WidgetConfiguration {
StaticConfiguration(kind: kind, provider: Provider(context: PersistenceController.shared.managedObjectContext)) { entry in
TimerWidgetEntryView(entry: entry)
.environment(\.managedObjectContext, PersistenceController.shared.managedObjectContext)
}
.configurationDisplayName("My Widget")
}
}
Xcode: Version 12.0.1
iOS: 14.0