From b45120706bd7bd778ad573cb3b80ef2879dda1fc Mon Sep 17 00:00:00 2001 From: Satindar Dhillon Date: Wed, 11 May 2022 16:23:22 -0700 Subject: [PATCH] fix linkeditem and labels data relationships. reset coredata on new app installs --- .../App/Views/Labels/LabelsViewModel.swift | 2 +- .../CoreDataModel.xcdatamodel/contents | 5 +- .../Services/DataService/DataService.swift | 49 +++++++++++++++++-- .../Mutations/RemoveLabelPublisher.swift | 6 +-- .../UpdateArticleLabelsPublisher.swift | 9 ++-- .../InternalLinkedItemLabel.swift | 8 +-- .../Sources/Utils/UserDefaultKeys.swift | 1 + 7 files changed, 59 insertions(+), 21 deletions(-) diff --git a/apple/OmnivoreKit/Sources/App/Views/Labels/LabelsViewModel.swift b/apple/OmnivoreKit/Sources/App/Views/Labels/LabelsViewModel.swift index e0a7aa062..06b8ceefb 100644 --- a/apple/OmnivoreKit/Sources/App/Views/Labels/LabelsViewModel.swift +++ b/apple/OmnivoreKit/Sources/App/Views/Labels/LabelsViewModel.swift @@ -64,7 +64,7 @@ import Views } func saveItemLabelChanges(itemID: String, dataService: DataService) { - dataService.updateItemLabels(itemID: itemID, labelNames: selectedLabels.map(\.unwrappedName)) + dataService.updateItemLabels(itemID: itemID, labelIDs: selectedLabels.map(\.unwrappedID)) } func addLabelToItem(_ label: LinkedItemLabel) { diff --git a/apple/OmnivoreKit/Sources/Models/CoreData/CoreDataModel.xcdatamodeld/CoreDataModel.xcdatamodel/contents b/apple/OmnivoreKit/Sources/Models/CoreData/CoreDataModel.xcdatamodeld/CoreDataModel.xcdatamodel/contents index 8b34e1252..183be56df 100644 --- a/apple/OmnivoreKit/Sources/Models/CoreData/CoreDataModel.xcdatamodeld/CoreDataModel.xcdatamodel/contents +++ b/apple/OmnivoreKit/Sources/Models/CoreData/CoreDataModel.xcdatamodeld/CoreDataModel.xcdatamodel/contents @@ -41,7 +41,7 @@ - + @@ -55,6 +55,7 @@ + @@ -85,7 +86,7 @@ - + diff --git a/apple/OmnivoreKit/Sources/Services/DataService/DataService.swift b/apple/OmnivoreKit/Sources/Services/DataService/DataService.swift index 145e0dade..3528a3dab 100644 --- a/apple/OmnivoreKit/Sources/Services/DataService/DataService.swift +++ b/apple/OmnivoreKit/Sources/Services/DataService/DataService.swift @@ -3,6 +3,7 @@ import CoreData import Foundation import Models import OSLog +import Utils let logger = Logger(subsystem: "app.omnivore", category: "data-service") @@ -13,8 +14,8 @@ public final class DataService: ObservableObject { public let appEnvironment: AppEnvironment let networker: Networker - let persistentContainer: PersistentContainer - let backgroundContext: NSManagedObjectContext + var persistentContainer: PersistentContainer + var backgroundContext: NSManagedObjectContext var subscriptions = Set() public var viewContext: NSManagedObjectContext { @@ -28,9 +29,13 @@ public final class DataService: ObservableObject { self.backgroundContext = persistentContainer.newBackgroundContext() backgroundContext.mergePolicy = NSMergePolicy.mergeByPropertyObjectTrump - persistentContainer.loadPersistentStores { _, error in - if let error = error { - fatalError("Core Data store failed to load with error: \(error)") + if isFirstTimeRunningNewAppVersion() { + resetCoreData() + } else { + persistentContainer.loadPersistentStores { _, error in + if let error = error { + fatalError("Core Data store failed to load with error: \(error)") + } } } } @@ -49,4 +54,38 @@ public final class DataService: ObservableObject { fatalError("Unable to write to Keychain: \(error)") } } + + private func resetCoreData() { + let storeContainer = + persistentContainer.persistentStoreCoordinator + + do { + for store in storeContainer.persistentStores { + try storeContainer.destroyPersistentStore( + at: store.url!, + ofType: store.type, + options: nil + ) + } + persistentContainer = PersistentContainer.make() + persistentContainer.loadPersistentStores { _, error in + if let error = error { + fatalError("Core Data store failed to load with error: \(error)") + } + } + backgroundContext = persistentContainer.newBackgroundContext() + } catch { + logger.debug("Failed to reset core data stores") + } + } + + private func isFirstTimeRunningNewAppVersion() -> Bool { + let appVersion = Bundle.main.object(forInfoDictionaryKey: "CFBundleShortVersionString") + guard let appVersion = appVersion as? String else { return false } + + let lastUsedAppVersion = UserDefaults.standard.string(forKey: UserDefaultKey.lastUsedAppVersion.rawValue) + let isFirstRun = (lastUsedAppVersion ?? "unknown") != appVersion + UserDefaults.standard.set(appVersion, forKey: UserDefaultKey.lastUsedAppVersion.rawValue) + return isFirstRun + } } diff --git a/apple/OmnivoreKit/Sources/Services/DataService/Mutations/RemoveLabelPublisher.swift b/apple/OmnivoreKit/Sources/Services/DataService/Mutations/RemoveLabelPublisher.swift index 30e6844ce..fc7c02c2b 100644 --- a/apple/OmnivoreKit/Sources/Services/DataService/Mutations/RemoveLabelPublisher.swift +++ b/apple/OmnivoreKit/Sources/Services/DataService/Mutations/RemoveLabelPublisher.swift @@ -7,7 +7,7 @@ extension DataService { // Update CoreData backgroundContext.perform { [weak self] in guard let self = self else { return } - guard let label = LinkedItemLabel.lookup(byName: name, inContext: self.backgroundContext) else { return } + guard let label = LinkedItemLabel.lookup(byID: labelID, inContext: self.backgroundContext) else { return } label.remove(inContext: self.backgroundContext) // Send update to server @@ -15,7 +15,7 @@ extension DataService { } } - func syncLabelDeletion(labelID: String, labelName: String) { + func syncLabelDeletion(labelID: String, labelName _: String) { enum MutationResult { case success(labelID: String) case error(errorCode: Enums.DeleteLabelErrorCode) @@ -43,7 +43,7 @@ extension DataService { let isSyncSuccess = data != nil context.perform { - let label = LinkedItemLabel.lookup(byName: labelName, inContext: context) + let label = LinkedItemLabel.lookup(byID: labelID, inContext: context) guard let label = label else { return } if isSyncSuccess { diff --git a/apple/OmnivoreKit/Sources/Services/DataService/Mutations/UpdateArticleLabelsPublisher.swift b/apple/OmnivoreKit/Sources/Services/DataService/Mutations/UpdateArticleLabelsPublisher.swift index 9b4fa549d..cab778898 100644 --- a/apple/OmnivoreKit/Sources/Services/DataService/Mutations/UpdateArticleLabelsPublisher.swift +++ b/apple/OmnivoreKit/Sources/Services/DataService/Mutations/UpdateArticleLabelsPublisher.swift @@ -4,7 +4,7 @@ import Models import SwiftGraphQL extension DataService { - public func updateItemLabels(itemID: String, labelNames: [String]) { + public func updateItemLabels(itemID: String, labelIDs: [String]) { backgroundContext.perform { [weak self] in guard let self = self else { return } guard let linkedItem = LinkedItem.lookup(byID: itemID, inContext: self.backgroundContext) else { return } @@ -13,12 +13,9 @@ extension DataService { linkedItem.removeFromLabels(existingLabels) } - var labelIDs = [String]() - - for labelName in labelNames { - if let labelObject = LinkedItemLabel.lookup(byName: labelName, inContext: self.backgroundContext) { + for labelID in labelIDs { + if let labelObject = LinkedItemLabel.lookup(byID: labelID, inContext: self.backgroundContext) { linkedItem.addToLabels(labelObject) - labelIDs.append(labelObject.unwrappedID) } } diff --git a/apple/OmnivoreKit/Sources/Services/InternalModels/InternalLinkedItemLabel.swift b/apple/OmnivoreKit/Sources/Services/InternalModels/InternalLinkedItemLabel.swift index ca31ae33e..f54cf6f8b 100644 --- a/apple/OmnivoreKit/Sources/Services/InternalModels/InternalLinkedItemLabel.swift +++ b/apple/OmnivoreKit/Sources/Services/InternalModels/InternalLinkedItemLabel.swift @@ -29,8 +29,8 @@ struct InternalLinkedItemLabel { } func asManagedObject(inContext context: NSManagedObjectContext) -> LinkedItemLabel { - let existingItem = LinkedItemLabel.lookup(byName: name, inContext: context) - let label = existingItem ?? LinkedItemLabel(entity: LinkedItemLabel.entity(), insertInto: context) + let existingLabel = LinkedItemLabel.lookup(byID: id, inContext: context) + let label = existingLabel ?? LinkedItemLabel(entity: LinkedItemLabel.entity(), insertInto: context) label.id = id label.name = name label.color = color @@ -44,10 +44,10 @@ extension LinkedItemLabel { public var unwrappedID: String { id ?? "" } public var unwrappedName: String { name ?? "" } - static func lookup(byName name: String, inContext context: NSManagedObjectContext) -> LinkedItemLabel? { + static func lookup(byID id: String, inContext context: NSManagedObjectContext) -> LinkedItemLabel? { let fetchRequest: NSFetchRequest = LinkedItemLabel.fetchRequest() fetchRequest.predicate = NSPredicate( - format: "%K == %@", #keyPath(LinkedItemLabel.name), name + format: "id == %@", id ) var label: LinkedItemLabel? diff --git a/apple/OmnivoreKit/Sources/Utils/UserDefaultKeys.swift b/apple/OmnivoreKit/Sources/Utils/UserDefaultKeys.swift index faa4d1e65..c32f00401 100644 --- a/apple/OmnivoreKit/Sources/Utils/UserDefaultKeys.swift +++ b/apple/OmnivoreKit/Sources/Utils/UserDefaultKeys.swift @@ -6,4 +6,5 @@ public enum UserDefaultKey: String { case firebasePushToken case homeFeedlayoutPreference case lastSelectedLinkedItemFilter + case lastUsedAppVersion }