import CoreData import CloudKit struct PersistenceController { static let shared = PersistenceController() let container: NSPersistentCloudKitContainer // CloudKit container identifier - same as iOS app for sync static let cloudKitContainerIdentifier = "iCloud.dev.rzen.indie.Workouts" var viewContext: NSManagedObjectContext { container.viewContext } // MARK: - Preview Support static var preview: PersistenceController = { let controller = PersistenceController(inMemory: true) let viewContext = controller.container.viewContext // Create sample data for previews let split = Split(context: viewContext) split.name = "Upper Body" split.color = "blue" split.systemImage = "dumbbell.fill" split.order = 0 let exercise = Exercise(context: viewContext) exercise.name = "Bench Press" exercise.sets = 3 exercise.reps = 10 exercise.weight = 135 exercise.order = 0 exercise.loadType = Int32(LoadType.weight.rawValue) exercise.split = split do { try viewContext.save() } catch { let nsError = error as NSError fatalError("Unresolved error \(nsError), \(nsError.userInfo)") } return controller }() // MARK: - Initialization init(inMemory: Bool = false, cloudKitEnabled: Bool = true) { container = NSPersistentCloudKitContainer(name: "Workouts") guard let description = container.persistentStoreDescriptions.first else { fatalError("Failed to retrieve a persistent store description.") } if inMemory { description.url = URL(fileURLWithPath: "/dev/null") description.cloudKitContainerOptions = nil } else if cloudKitEnabled { // Check if CloudKit is available before enabling let cloudKitAvailable = FileManager.default.ubiquityIdentityToken != nil if cloudKitAvailable { // Set CloudKit container options let cloudKitOptions = NSPersistentCloudKitContainerOptions( containerIdentifier: Self.cloudKitContainerIdentifier ) description.cloudKitContainerOptions = cloudKitOptions } else { // CloudKit not available (not signed in, etc.) description.cloudKitContainerOptions = nil print("CloudKit not available - using local storage only") } // Enable persistent history tracking (useful even without CloudKit) description.setOption(true as NSNumber, forKey: NSPersistentHistoryTrackingKey) description.setOption(true as NSNumber, forKey: NSPersistentStoreRemoteChangeNotificationPostOptionKey) } else { // CloudKit explicitly disabled description.cloudKitContainerOptions = nil } container.loadPersistentStores { storeDescription, error in if let error = error as NSError? { // In production, handle this more gracefully print("CoreData error: \(error), \(error.userInfo)") #if DEBUG fatalError("Unresolved error \(error), \(error.userInfo)") #endif } } // Configure view context container.viewContext.automaticallyMergesChangesFromParent = true container.viewContext.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy // Pin the viewContext to the current generation token do { try container.viewContext.setQueryGenerationFrom(.current) } catch { print("Failed to pin viewContext to the current generation: \(error)") } } // MARK: - Save Context func save() { let context = container.viewContext if context.hasChanges { do { try context.save() } catch { let nsError = error as NSError print("Save error: \(nsError), \(nsError.userInfo)") } } } }