From dbd50eced04308d7ab240f3f30672602e6112220 Mon Sep 17 00:00:00 2001 From: Laurent Date: Tue, 3 Jun 2025 10:41:17 +0200 Subject: [PATCH] Adds StoreLibrary to manage stores + fix init bug --- LeStorage.xcodeproj/project.pbxproj | 4 ++ LeStorage/StoreCenter.swift | 60 +++++++++------------------ LeStorage/StoreLibrary.swift | 63 +++++++++++++++++++++++++++++ LeStorage/StoredCollection.swift | 4 +- 4 files changed, 86 insertions(+), 45 deletions(-) create mode 100644 LeStorage/StoreLibrary.swift diff --git a/LeStorage.xcodeproj/project.pbxproj b/LeStorage.xcodeproj/project.pbxproj index d77ab30..04c9d4b 100644 --- a/LeStorage.xcodeproj/project.pbxproj +++ b/LeStorage.xcodeproj/project.pbxproj @@ -22,6 +22,7 @@ C488C8802CCBDC210082001F /* NetworkMonitor.swift in Sources */ = {isa = PBXBuildFile; fileRef = C488C87F2CCBDC210082001F /* NetworkMonitor.swift */; }; C49774DF2DC4B3D7005CD239 /* SyncData.swift in Sources */ = {isa = PBXBuildFile; fileRef = C49774DE2DC4B3D7005CD239 /* SyncData.swift */; }; C49779FC2DDB5D89005CD239 /* String+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = C49779FB2DDB5D89005CD239 /* String+Extensions.swift */; }; + C4977BA92DEDFE6D005CD239 /* StoreLibrary.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4977BA82DEDFE6D005CD239 /* StoreLibrary.swift */; }; C49B6E502C2089B6002BDE1B /* ApiCallCollection.swift in Sources */ = {isa = PBXBuildFile; fileRef = C49B6E4F2C2089B6002BDE1B /* ApiCallCollection.swift */; }; C49EF0242BD6BDC50077B5AA /* FileManager+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = C49EF0232BD6BDC50077B5AA /* FileManager+Extensions.swift */; }; C4A47D4F2B6D280200ADC637 /* StoredCollection.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4A47D4E2B6D280200ADC637 /* StoredCollection.swift */; }; @@ -81,6 +82,7 @@ C488C87F2CCBDC210082001F /* NetworkMonitor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NetworkMonitor.swift; sourceTree = ""; }; C49774DE2DC4B3D7005CD239 /* SyncData.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SyncData.swift; sourceTree = ""; }; C49779FB2DDB5D89005CD239 /* String+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "String+Extensions.swift"; sourceTree = ""; }; + C4977BA82DEDFE6D005CD239 /* StoreLibrary.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StoreLibrary.swift; sourceTree = ""; }; C49B6E4F2C2089B6002BDE1B /* ApiCallCollection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ApiCallCollection.swift; sourceTree = ""; }; C49EF0232BD6BDC50077B5AA /* FileManager+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "FileManager+Extensions.swift"; sourceTree = ""; }; C4A47D4E2B6D280200ADC637 /* StoredCollection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StoredCollection.swift; sourceTree = ""; }; @@ -169,6 +171,7 @@ C4AC9CE92CF754CC00CC13DF /* Relationship.swift */, C4A47D602B6D3C1300ADC637 /* Services.swift */, C425D4572B6D2519002A7B48 /* Store.swift */, + C4977BA82DEDFE6D005CD239 /* StoreLibrary.swift */, C4FC2E282C2B2EC30021F3BF /* StoreCenter.swift */, C4A47D642B6E92FE00ADC637 /* Storable.swift */, C4A47D4E2B6D280200ADC637 /* StoredCollection.swift */, @@ -366,6 +369,7 @@ C4D477972CB66EEA0077713D /* Date+Extensions.swift in Sources */, C488C8802CCBDC210082001F /* NetworkMonitor.swift in Sources */, C4A47D6D2B71364600ADC637 /* ModelObject.swift in Sources */, + C4977BA92DEDFE6D005CD239 /* StoreLibrary.swift in Sources */, C49779FC2DDB5D89005CD239 /* String+Extensions.swift in Sources */, C400D7232CC2AF560092237C /* GetSyncData.swift in Sources */, C4A47D4F2B6D280200ADC637 /* StoredCollection.swift in Sources */, diff --git a/LeStorage/StoreCenter.swift b/LeStorage/StoreCenter.swift index 612e3b3..d85ee98 100644 --- a/LeStorage/StoreCenter.swift +++ b/LeStorage/StoreCenter.swift @@ -9,16 +9,15 @@ import Foundation import UIKit public class StoreCenter { - + /// The main instance public static let main: StoreCenter = StoreCenter() + fileprivate lazy var _storeLibrary: StoreLibrary = { StoreLibrary(storeCenter: self) }() + /// The name of the directory to store the json files let directoryName: String - /// A dictionary of Stores associated to their id - fileprivate var _stores: [String: Store] = [:] - /// Returns a default Store instance public lazy var mainStore: Store = { Store(storeCenter: self) }() @@ -185,50 +184,29 @@ public class StoreCenter { // MARK: - Store management - /// Registers a store into the list of stores - /// - Parameters: - /// - store: A store to save - fileprivate func _registerStore(store: Store) { - guard let identifier = store.identifier else { - fatalError("The store has no identifier") - } - if self._stores[identifier] != nil { - fatalError("A store with this identifier has already been registered: \(identifier)") - } - self._stores[identifier] = store - } - - /// Returns a store using its identifier, and registers it if it does not exists - /// - Parameters: - /// - identifier: The store identifer - /// - parameter: The parameter name used to filter data on the server func requestStore(identifier: String) -> Store { - if let store = self._stores[identifier] { - return store - } else { - let store = Store(storeCenter: self, identifier: identifier) - self._registerStore(store: store) - return store - } + return self._storeLibrary.requestStore(identifier: identifier) } /// Returns the store corresponding to the provided id, and creates one if necessary, otherwise returns the main store fileprivate func _requestStore(id: String?) -> Store { if let storeId = id { - if let store = self._stores[storeId] { - return store - } else { - let store = Store(storeCenter: self, identifier: storeId) - self._registerStore(store: store) - return store - } + return self._storeLibrary.requestStore(identifier: storeId) + +// if let store = self._stores[storeId] { +// return store +// } else { +// let store = Store(storeCenter: self, identifier: storeId) +// self._registerStore(store: store) +// return store +// } } else { return self.mainStore } } fileprivate func _store(id: String?) -> Store { - if let storeId = id, let store = self._stores[storeId] { + if let storeId = id, let store = self._storeLibrary[storeId] { return store } else { return self.mainStore @@ -236,7 +214,7 @@ public class StoreCenter { } public func store(identifier: String) throws -> Store { - if let store = self._stores[identifier] { + if let store = self._storeLibrary[identifier] { return store } throw StoreError.storeNotRegistered(id: identifier) @@ -246,9 +224,7 @@ public class StoreCenter { /// - Parameters: /// - identifier: The name of the directory public func destroyStore(identifier: String) { - let directory = "\(self.directoryName)/\(identifier)" - FileManager.default.deleteDirectoryInDocuments(directoryName: directory) - self._stores.removeValue(forKey: identifier) + self._storeLibrary.destroyStore(identifier: identifier) } // MARK: - Settings @@ -290,7 +266,7 @@ public class StoreCenter { self.resetApiCalls() self._failedAPICallsCollection?.reset() - self._stores.removeAll() + self._storeLibrary.reset() self.dataAccessCollection?.reset() self._deleteLogs.reset() @@ -840,7 +816,7 @@ public class StoreCenter { func relationshipStore(instance: T, relationship: Relationship) -> Store? { switch relationship.storeLookup { case .main: return Store.main - case .child: return self._stores[instance.stringId] + case .child: return self._storeLibrary[instance.stringId] case .same: return instance.store } } diff --git a/LeStorage/StoreLibrary.swift b/LeStorage/StoreLibrary.swift new file mode 100644 index 0000000..e8ede18 --- /dev/null +++ b/LeStorage/StoreLibrary.swift @@ -0,0 +1,63 @@ +// +// StoreLibrary.swift +// LeStorage +// +// Created by Laurent Morvillier on 02/06/2025. +// + +import Foundation + +class StoreLibrary { + + private let storeCenter: StoreCenter + + /// A dictionary of Stores associated to their id + fileprivate var _stores: [String: Store] = [:] + + init(storeCenter: StoreCenter) { + self.storeCenter = storeCenter + } + + subscript(identifier: String) -> Store? { + get { + return self._stores[identifier] + } + } + + /// Registers a store into the list of stores + /// - Parameters: + /// - store: A store to save + fileprivate func _registerStore(store: Store) { + guard let identifier = store.identifier else { + fatalError("The store has no identifier") + } + if self._stores[identifier] != nil { + fatalError("A store with this identifier has already been registered: \(identifier)") + } + self._stores[identifier] = store + } + + /// Returns a store using its identifier, and registers it if it does not exists + /// - Parameters: + /// - identifier: The store identifer + /// - parameter: The parameter name used to filter data on the server + func requestStore(identifier: String) -> Store { + if let store = self._stores[identifier] { + return store + } else { + let store = Store(storeCenter: self.storeCenter, identifier: identifier) + self._registerStore(store: store) + return store + } + } + + public func destroyStore(identifier: String) { + let directory = "\(self.storeCenter.directoryName)/\(identifier)" + FileManager.default.deleteDirectoryInDocuments(directoryName: directory) + self._stores.removeValue(forKey: identifier) + } + + func reset() { + self._stores.removeAll() + } +} diff --git a/LeStorage/StoredCollection.swift b/LeStorage/StoredCollection.swift index 11c48ea..56c3bf0 100644 --- a/LeStorage/StoredCollection.swift +++ b/LeStorage/StoredCollection.swift @@ -201,10 +201,8 @@ public class StoredCollection: SomeCollection { /// Sets a collection of items and indexes them func setItems(_ items: [T]) { for item in items { - item.store = self.store + self.addItem(instance: item) } - self.items = items - self._updateIndexIfNecessary() } @MainActor