The app uses Core Data + CloudKit. When the app gets launched WidgetKit file fetches correct entries from Core Data but when I add new entries to Core Data from the main app and call WidgetCenter.shared.reloadTimelines() updated entries don't get fetched and old data is displayed inside the widget.
Main app and Widget target have the same App group, iCloud capability enabled for both targets.
When I call WidgetCenter.shared.reloadTimelines() from the Main app Widget reloads (timer added to Widget view sets to zero) but fetch from Core Data doesn't return newly added entries. Then I restart the app and correct entries get fetched.
Why doesn't it fetch correct entries when WidgetCenter.shared.reloadTimelines() gets called and only works when app is relaunched?
Widget's code:
import WidgetKit
import SwiftUI
import CoreData
struct Provider: TimelineProvider {
		func placeholder(in context: Context) -> HabitsEntry {
				HabitsEntry(date: Date(), habitsCount: 0)
		}
		func getSnapshot(in context: Context, completion: @escaping (HabitsEntry) -> ()) {
				let entry = HabitsEntry(date: Date(), habitsCount: 0)
				completion(entry)
		}
		func getTimeline(in context: Context, completion: @escaping (Timeline<Entry>) -> ()) {				
				let managedObjectContext = Storage.viewContext
				let request = NSFetchRequest<NSFetchRequestResult>(entityName: "DailyHabit")
				let predicate = Storage.getCurrentDatePredicate()
				request.predicate = predicate
				var habits = 0
				do { habits = try managedObjectContext.count(for: request)	}
				catch let error as NSError {print ("Could not fetch \(error), \(error.userInfo)")}
				let entry = [HabitsEntry(date: Date(), habitsCount: habits)]
				let timeline = Timeline(entries: entry, policy: .never)
				completion(timeline)
		}
}
struct HabitsEntry: TimelineEntry {
		let date: Date
		var habitsCount: Int
}
struct HabitsHomeWidgetEntryView : View {
		var entry: Provider.Entry
		var body: some View {
			Text(entry.date, style: .timer)
			Text("There are \(entry.habitsCount) daily habits")
		}
}
@main
struct HabitsHomeWidget: Widget {
		let kind: String = "HabitsHomeWidget"
		var body: some WidgetConfiguration {
				StaticConfiguration(kind: kind, provider: Provider()) { entry in
						HabitsHomeWidgetEntryView(entry: entry)
				}
				.configurationDisplayName("My Widget")
				.description("This is an example widget.")
		}
}	
Here is the code for Core Data:
import UIKit
import CoreData
import WidgetKit
class Storage {
	
	static let shared = Storage()
	
	static var persistentContainer: NSPersistentContainer {
		return Storage.shared.persistentContainer
	}
	
	static var viewContext: NSManagedObjectContext {
		return persistentContainer.viewContext
	}
	
	lazy var persistentContainer: NSPersistentContainer = {
		let container: NSPersistentContainer
		
		let containerURL = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: Constants.appGroupName)!
		let storeURL = containerURL.appendingPathComponent("NoRegrets.sqlite")
		let description = NSPersistentStoreDescription(url: storeURL)
		if isICloudContainerAvailable {
			container = NSPersistentCloudKitContainer(name: Constants.persistentContainerName)
		} else {
			container = NSPersistentContainer(name: Constants.persistentContainerName)
		}
		description.setOption(true as NSNumber, forKey: NSPersistentHistoryTrackingKey)
		description.setOption(true as NSNumber, forKey: NSPersistentStoreRemoteChangeNotificationPostOptionKey)
		description.shouldMigrateStoreAutomatically = true
		description.shouldInferMappingModelAutomatically = true
		let storeDescription = description
		
		container.persistentStoreDescriptions = [storeDescription]
		
		container.loadPersistentStores(completionHandler: { (storeDescription, error) in
			if let error = error as NSError? {
				return
			}
		})
		
		container.viewContext.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy
		container.viewContext.automaticallyMergesChangesFromParent = true
		
		do {
			try container.viewContext.setQueryGenerationFrom(.current)
		} catch {
			print("Failed to pin viewContext to the current generation: \(error)")
		}
		return container
	}()
	
	var isICloudContainerAvailable: Bool {
		FileManager.default.ubiquityIdentityToken != nil
	}
	
	// MARK: - Core Data Saving support
	func saveContext() {
		let context = persistentContainer.viewContext
		if context.hasChanges {
			do {
				try context.save()
				
			} catch {
				let nserror = error as NSError
				print("Saving error: \(nserror)")
			}
		}
	}
}
// MARK: - Helper methods
extension Storage {
	func getCurrentUser() -> User? {
		let fetchRequest = User.createFetchRequest()
		fetchRequest.fetchLimit = 1
		fetchRequest.sortDescriptors = [NSSortDescriptor(key: "objectID", ascending: false)]
		
		let user = try? Storage.viewContext.fetch(fetchRequest).first
		return user
	}
	
	class func getCurrentDatePredicate() -> NSPredicate {
		var calendar = Calendar.current
		calendar.timeZone = NSTimeZone.local
		let dateFrom = calendar.startOfDay(for: Date())
		let dateTo = calendar.date(byAdding: .day, value: 1, to: dateFrom)
		let fromPredicate = NSPredicate(format: "date >= %@", dateFrom as NSDate)
		let toPredicate = NSPredicate(format: "date < %@", dateTo! as NSDate)
		return NSCompoundPredicate(andPredicateWithSubpredicates: [fromPredicate, toPredicate])
	}
}
Post
Replies
Boosts
Views
Activity
I have a project with a Mac Catalyst target that I can not build on my m1 mac (it works fine on my older intel mac). This is the error message: Could not read serialized diagnostics file: error("Invalid diagnostics signature") (in target 'LifeViewerMac' from project 'NoRegrets') Command CompileSwift failed with a nonzero exit code
Here's the xcode screenshot: