0

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

enter image description here

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

Tio
  • 944
  • 3
  • 15
  • 35

0 Answers0