ALL BUSINESS
COMIDA
DIRECTORIES
EDUCATIONAL
ENTERTAINMENT
FASHION TIPS
FINER THINGS
FREE CREATOR TOOLS
HEALTH
MARKETPLACE
MEMBER's ONLY
MONEY MATTER$
MOTIVATIONAL
NEWS & WEATHER
TECHNOLOGIA
TELEVISION NETWORKS
USA VOTES 2024
VIDEOS
INVESTOR RELATIONS
IN DEVELOPMENT
Posted by - Latinos MediaSyndication -
on - March 9, 2023 -
Filed in - Technology -
-
372 Views - 0 Comments - 0 Likes - 0 Reviews
I have a widget that shows me core data stuff data I modify in the app. All I want the widget to do is to refresh whenever the core data database in the main app refreshes.
Here is my widget
// // RemindMeWidget.swift // RemindMeWidget // // Created by Charel Felten on 05/07/2021. // import WidgetKit import SwiftUI import Intents import CoreData struct Provider: IntentTimelineProvider { func placeholder(in context: Context) -> SimpleEntry { SimpleEntry( date: Date(), configuration: ConfigurationIntent(), notes: Note.previewNotes, realFamily: context.family ) } func getSnapshot(for configuration: ConfigurationIntent, in context: Context, completion: @escaping (SimpleEntry) -> ()) { let entry = SimpleEntry( date: Date(), configuration: configuration, notes: Note.previewNotes, realFamily: context.family ) completion(entry) } func getTimeline(for configuration: ConfigurationIntent, in context: Context, completion: @escaping (Timeline<Entry>) -> ()) { print("get timeline is called") var notes: [Note] = [] let containerURL = PersistenceController.containerURL let storeURL = containerURL.appendingPathComponent(PersistenceController.SQLiteStoreAppendix) let description = NSPersistentStoreDescription(url: storeURL) let container = NSPersistentCloudKitContainer(name: PersistenceController.containerName) container.persistentStoreDescriptions = [description] container.loadPersistentStores(completionHandler: { (storeDescription, error) in if let error = error as NSError? { fatalError("Unresolved error \(error), \(error.userInfo)") } }) let viewContext = PersistenceController.shared.container.viewContext let request = NSFetchRequest<NSFetchRequestResult>(entityName: "Note") do { let result = try viewContext.fetch(request) // is there a nicer way to do it? if let tmp = result as? [Note] { notes = tmp } } catch { let nsError = error as NSError fatalError("Unresolved error \(nsError), \(nsError.userInfo)") } notes = notes.sorted { (lhs, rhs) in if lhs.int16priority == rhs.int16priority { return lhs.timestamp! > rhs.timestamp! } return lhs.int16priority > rhs.int16priority } let entry = SimpleEntry( date: Date(), configuration: configuration, notes: notes, realFamily: context.family ) print("hey") let timeline = Timeline(entries: [entry], policy: .atEnd) completion(timeline) } } struct SimpleEntry: TimelineEntry { let date: Date let configuration: ConfigurationIntent var notes: [Note] var realFamily: WidgetFamily } struct RemindMeWidgetEntryView : View { var entry: Provider.Entry var body: some View { WidgetView(notes: entry.notes, realFamily: entry.realFamily) } } @main struct RemindMeWidget: Widget { let kind: String = "RemindMeWidget" var body: some WidgetConfiguration { IntentConfiguration(kind: kind, intent: ConfigurationIntent.self, provider: Provider()) { entry in RemindMeWidgetEntryView(entry: entry) } .configurationDisplayName("My Widget") .description("This is an example widget.") } } struct RemindMeWidget_Previews: PreviewProvider { static var previews: some View { RemindMeWidgetEntryView( entry: SimpleEntry( date: Date(), configuration: ConfigurationIntent(), notes: Note.previewNotes, realFamily: .systemSmall ) ).previewContext(WidgetPreviewContext(family: .systemSmall)) } }
In the app, I have a settings page where I call a manual widget refresh (for debugging for now) like this:
Button("Reload Widget") { print("calling widgetcenter") WidgetCenter.shared.reloadAllTimelines() WidgetCenter.shared.getCurrentConfigurations({result in print(result)}) }
Full code:
// // SettingsView.swift // RemindMe // // Created by Charel Felten on 02/07/2021. // import SwiftUI import WidgetKit struct SettingsView: View { @Environment(\.colorScheme) var colorScheme @ObservedObject var config: Config var body: some View { NavigationView { Form { ForEach(Priority.allRegularCases) { priority in PriorityView(config: config, priority: priority) } Section(header: Text("Theme")) { Picker(selection: $config.colorTheme, label: Text("Theme")) { ForEach(ColorTheme.allCases, id: \.self) { value in Text(value.rawValue).tag(value) } } } Section(header: Text("Additional Info"), footer: Text("Toggle which additional information to show below each note in the list.")) { Toggle(isOn: $config.showNotificationTime) { Text("Show reminders") } Toggle(isOn: $config.showCreationTime) { Text("Show date") } Button("Reload Widget") { print("calling widgetcenter") WidgetCenter.shared.reloadAllTimelines() WidgetCenter.shared.getCurrentConfigurations({result in print(result)}) } } } .navigationTitle("Settings") } // save the settings if we leave the app (goes away from foreground) .onReceive( NotificationCenter.default.publisher(for: UIApplication.willResignActiveNotification), perform: { _ in config.save() } ) .onDisappear(perform: Note.updateAllNotes) } } struct PriorityView: View { @Environment(\.colorScheme) var colorScheme @ObservedObject var config: Config var priority: Priority var body: some View { Section(header: Text(priority.getDescription()).foregroundColor(Color.secondary)) { Picker(selection: $config.priorityIntervals[priority.getIndex()], label: Text("Notification interval")) { ForEach(Interval.allCases, id: \.self) { value in Text(value.rawValue).tag(value) } } switch config.priorityIntervals[priority.getIndex()] { case .ten_minutes, .never: EmptyView() default: DatePicker("Reminders at", selection: $config.priorityDates[priority.getIndex()], displayedComponents: [.hourAndMinute]) } } .foregroundColor(Colors.getColor(for: priority, in: .primary)) .listRowBackground( ZStack { colorScheme == .dark ? Color.black : Color.white Colors.getColor(for: priority, in: .background) } ) } } struct SettingsView_Previews: PreviewProvider { static var previews: some View { SettingsView( config: Config() ) } }
Clicking this button prints the following to my console:
calling widgetcenter success([WidgetInfo: - configuration: <ConfigurationIntent: 0x282e51dd0> { } - family: systemSmall - kind: RemindMeWidget, WidgetInfo: - configuration: <ConfigurationIntent: 0x282e51e60> { } - family: systemLarge - kind: RemindMeWidget, WidgetInfo: - configuration: <ConfigurationIntent: 0x282e51ef0> { } - family: systemMedium - kind: RemindMeWidget])
The widget however is not refreshed. It keeps looking like this:
Sometimes I did refresh, but then when I made changes in the app, the widget did not update. None of the print statements that I put in getTimeline are being printed. I am really exhausted and not sure what I did wrong...
I am sorry for posting this much code and not a smaller reproducible example, but I just have not idea whatsoever where the issue could come from.
I have read multiple related questions but none of them have helped
If you want to take a look at the code, here it is:
https://github.com/charelF/RemindMeApp/tree/main/RemindMeWidget
small updateits also not working in the simulator.
I pushed all my changes to github, see https://github.com/charelF/RemindMeApp
Im opening a bounty, will award it to whoever helps me find my problem.