I have a CoreData database, and I have attempted to migrate it to an app group to share it between my main app and a widget extension. The database seems that seems to be fetched by the app and the widget seem to be completely separate from each other.
My CoreData code (persistence.swift)
import CoreData
struct PersistenceController {
static let shared = PersistenceController()
static var preview: PersistenceController = {
let result = PersistenceController(inMemory: true)
let viewContext = result.container.viewContext
let newUserData = Userdata(context: viewContext)
newUserData.hourly = 15.3
let newSession = Session(context: viewContext)
newSession.id = UUID()
newSession.start = Date()
newSession.end = Date()
do {
try viewContext.save()
} catch {
let nsError = error as NSError
fatalError("Unresolved error \(nsError), \(nsError.userInfo)")
}
return result
}()
let container: NSPersistentContainer
init(inMemory: Bool = false) {
container = NSPersistentContainer(name: "FManger")
let storeURL = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: "group.omaribrahim-uchicago.FManger")!.appendingPathComponent("FManger.sqlite")
var defaultURL: URL?
if let storeDescription = container.persistentStoreDescriptions.first, let url = storeDescription.url {
defaultURL = FileManager.default.fileExists(atPath: url.path) ? url : nil
}
if defaultURL == nil {
container.persistentStoreDescriptions = [NSPersistentStoreDescription(url: storeURL)]
}
container.loadPersistentStores(completionHandler: { [unowned container] (storeDescription, error) in
if let error = error as NSError? {
fatalError("Unresolved error \(error), \(error.userInfo)")
}
if let url = defaultURL, url.absoluteString != storeURL.absoluteString {
let coordinator = container.persistentStoreCoordinator
if let oldStore = coordinator.persistentStore(for: url) {
do {
try coordinator.migratePersistentStore(oldStore, to: storeURL, options: nil, withType: NSSQLiteStoreType)
} catch {
print(error.localizedDescription)
}
// delete old store
let fileCoordinator = NSFileCoordinator(filePresenter: nil)
fileCoordinator.coordinate(writingItemAt: url, options: .forDeleting, error: nil, byAccessor: { url in
do {
try FileManager.default.removeItem(at: url)
} catch {
print(error.localizedDescription)
}
})
}
}
})
}
}
My Widget data constructor and main function
import WidgetKit
import SwiftUI
import Intents
struct Provider: IntentTimelineProvider {
func placeholder(in context: Context) -> SimpleEntry {
SimpleEntry(date: Date(), data: .previewData, error: false, configuration: ConfigurationIntent())
}
func getSnapshot(for configuration: ConfigurationIntent, in context: Context, completion: @escaping (SimpleEntry) -> ()) {
let entry = SimpleEntry(date: Date(), data: .previewData, error: false, configuration: configuration)
completion(entry)
}
func getTimeline(for configuration: ConfigurationIntent, in context: Context, completion: @escaping (Timeline<Entry>) -> ()) {
var entries: [SimpleEntry] = []
@FetchRequest(
sortDescriptors:[NSSortDescriptor(key: "start", ascending: false)],
animation: .default)
var sessions: FetchedResults<Session>
if (sessions.count > 0) {
let checkedIn = sessions[0].end != nil
let totalMinutes = totalMinutes(sessions: sessions)
var auxMinutes = 0.0
if (checkedIn) {
auxMinutes = timeBetween(fromDate: sessions[0].start!, toDate: Date())
}
let currentDate = Date()
for i in 0 ..< 5 {
let entryDate = Calendar.current.date(byAdding: .hour, value: i, to: currentDate)!
let cSession = fromMinutes(minutes: (Double(i) * 60) + auxMinutes)
let widgetData = SimpleEntry.PayData(currentSession: cSession,
grossTotal: totalMinutes * 15.3 + cSession,
paycheckDay: Date() + (7 * 24 * 60 * 60),
checkedIn: checkedIn)
let entry = SimpleEntry(date: entryDate,
data: widgetData,
error: false,
configuration: configuration)
entries.append(entry)
}
}
else {
let entry = SimpleEntry(date: Date(),
data: .error,
error: true,
configuration: configuration)
entries.append(entry)
}
let timeline = Timeline(entries: entries, policy: .atEnd)
completion(timeline)
}
}
@main
struct Widgets: Widget {
let kind: String = "Widgets"
let persistenceController = PersistenceController.shared
var body: some WidgetConfiguration {
IntentConfiguration(kind: kind, intent: ConfigurationIntent.self, provider: Provider()) { entry in
WidgetsEntryView(entry: entry)
.environment(\.managedObjectContext, persistenceController.container.viewContext)
}
.configurationDisplayName("Pay Tracker")
.description("Check your current shift's earning, total earnings, and the date of your next payment in a glance.")
}
}
I am pretty sure I did something wrong, but what is it?