From e8bcdefe1d31de0f34b7a90a9099f5b1fa11b455 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Junnos=20=EF=A3=BF?= Date: Mon, 11 Dec 2023 03:01:28 +0900 Subject: [PATCH] =?UTF-8?q?:bug:=20Persistable=20=ED=94=84=EB=A1=9C?= =?UTF-8?q?=ED=86=A0=EC=BD=9C=EC=9D=84=20=EB=AA=A8=EB=93=A0=20Repository?= =?UTF-8?q?=EC=97=90=EC=84=9C=20=EC=B1=84=ED=83=9D=ED=95=A0=20=EC=88=98=20?= =?UTF-8?q?=EC=9E=88=EB=8F=84=EB=A1=9D=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../FileManager/FileManagerStorage.swift | 1 - .../Protocol/MSPersistentStorage.swift | 1 + .../JourneyRepository+Persistable.swift | 115 ------------------ .../MSData/Repository/JourneyRepository.swift | 34 +++--- .../MSData/Repository/Persistable.swift | 96 +++++++++++++++ .../MSData/Repository/SpotRepository.swift | 6 +- .../PersistableRepositoryTests.swift | 2 +- 7 files changed, 118 insertions(+), 137 deletions(-) delete mode 100644 iOS/MSData/Sources/MSData/Repository/JourneyRepository+Persistable.swift diff --git a/iOS/MSCoreKit/Sources/MSPersistentStorage/FileManager/FileManagerStorage.swift b/iOS/MSCoreKit/Sources/MSPersistentStorage/FileManager/FileManagerStorage.swift index 06115d6..63165fb 100644 --- a/iOS/MSCoreKit/Sources/MSPersistentStorage/FileManager/FileManagerStorage.swift +++ b/iOS/MSCoreKit/Sources/MSPersistentStorage/FileManager/FileManagerStorage.swift @@ -84,7 +84,6 @@ public final class FileManagerStorage: NSObject, MSPersistentStorage { } MSLogger.make(category: .fileManager).error("경로의 Data를 성공적으로 가져왔습니다.") - print(dataPath.description) guard let data = try? Data(contentsOf: dataPath), let decodedData = try? self.decoder.decode(T.self, from: data) else { MSLogger.make(category: .fileManager).error("decode에 실패하였습니다.") diff --git a/iOS/MSCoreKit/Sources/MSPersistentStorage/Protocol/MSPersistentStorage.swift b/iOS/MSCoreKit/Sources/MSPersistentStorage/Protocol/MSPersistentStorage.swift index 66471c6..4d1a8ea 100644 --- a/iOS/MSCoreKit/Sources/MSPersistentStorage/Protocol/MSPersistentStorage.swift +++ b/iOS/MSCoreKit/Sources/MSPersistentStorage/Protocol/MSPersistentStorage.swift @@ -8,6 +8,7 @@ public protocol MSPersistentStorage { func get(_ type: T.Type, forKey key: String) -> T? + @discardableResult func set(value: T, forKey key: String) -> T? } diff --git a/iOS/MSData/Sources/MSData/Repository/JourneyRepository+Persistable.swift b/iOS/MSData/Sources/MSData/Repository/JourneyRepository+Persistable.swift deleted file mode 100644 index ad5b042..0000000 --- a/iOS/MSData/Sources/MSData/Repository/JourneyRepository+Persistable.swift +++ /dev/null @@ -1,115 +0,0 @@ -// -// JourneyRepository+Persistable.swift -// MSData -// -// Created by 전민건 on 12/10/23. -// - -import Foundation - -import MSDomain -import MSLogger -import MSPersistentStorage - -public protocol Persistable { - - func saveToLocal(value: Codable) -> Bool - func loadJourneyFromLocal() -> RecordingJourney? - -} - -// MARK: - Interface - -extension JourneyRepositoryImplementation: Persistable { - - private struct KeyStorage { - - static var id: String? = nil - static var startTimestamp: String? = nil - static var spots = [String]() - static var coordinates = [String]() - - } - - @discardableResult - public func saveToLocal(value: Codable) -> Bool { - let key = UUID().uuidString - self.storage.set(value: value, forKey: key) - - switch value { - case is String: - if KeyStorage.id == nil { - KeyStorage.id = key - } else { - MSLogger.make(category: .persistable).debug("journey ID는 하나의 값만 저장할 수 있습니다.") - return false - } - case is Date: - if KeyStorage.startTimestamp == nil { - KeyStorage.startTimestamp = key - } else { - MSLogger.make(category: .persistable).debug("start tamp는 하나의 값만 저장할 수 있습니다.") - return false - } - case is SpotDTO: - KeyStorage.spots.append(key) - case is CoordinateDTO: - KeyStorage.coordinates.append(key) - default: - MSLogger.make(category: .persistable).debug("RecordingJourney 타입의 요소들만 넣을 수 있습니다.") - return false - } - return true - } - - public func loadJourneyFromLocal() -> RecordingJourney? { - guard let id = self.loadID(), - let startTimestamp = self.loadStartTimeStamp() else { - return nil - } - return RecordingJourney(id: id, - startTimestamp: startTimestamp, - spots: self.loadSpots(), - coordinates: self.loadCoordinates()) - } - -} - -// MARK: - load Functions - -private extension JourneyRepositoryImplementation { - - func loadStartTimeStamp() -> Date? { - guard let startTimestampKey = KeyStorage.startTimestamp, - let startTimestamp = self.storage.get(Date.self, forKey: startTimestampKey) - else { - MSLogger.make(category: .persistable).debug("id 또는 startTimestamp가 저장되지 않았습니다.") - return nil - } - return startTimestamp - } - - func loadID() -> String? { - guard let idKey = KeyStorage.id, - let id = self.storage.get(String.self, forKey: idKey) else { - MSLogger.make(category: .persistable).debug("id 또는 startTimestamp가 저장되지 않았습니다.") - return nil - } - return id - } - - func loadSpots() -> [Spot] { - return KeyStorage.spots.compactMap { spotKey in - let spotDTO = self.storage.get(SpotDTO.self, forKey: spotKey) - return spotDTO?.toDomain() - } - } - - func loadCoordinates() -> [Coordinate] { - return KeyStorage.coordinates.compactMap { coordinateKey in - let coordinateDTO = self.storage.get(CoordinateDTO.self, forKey: coordinateKey) - return coordinateDTO?.toDomain() - } - } - -} diff --git a/iOS/MSData/Sources/MSData/Repository/JourneyRepository.swift b/iOS/MSData/Sources/MSData/Repository/JourneyRepository.swift index c6a69ee..978463f 100644 --- a/iOS/MSData/Sources/MSData/Repository/JourneyRepository.swift +++ b/iOS/MSData/Sources/MSData/Repository/JourneyRepository.swift @@ -34,21 +34,17 @@ public struct JourneyRepositoryImplementation: JourneyRepository { // MARK: - Properties private let networking: MSNetworking - private let persistent: MSPersistentStorage + public let storage: MSPersistentStorage @UserDefaultsWrapped(UserDefaultsKey.recordingJourneyID, defaultValue: nil) private var recordingJourneyID: String? - // MARK: - Properties: Persistable - - internal var storage = FileManagerStorage() - // MARK: - Initializer public init(session: URLSession = URLSession(configuration: .default), - fileManager: FileManager = FileManager()) { + persistentStorage: MSPersistentStorage = FileManagerStorage()) { self.networking = MSNetworking(session: session) - self.persistent = FileManagerStorage(fileManager: fileManager) + self.storage = persistentStorage } // MARK: - Functions @@ -62,13 +58,13 @@ public struct JourneyRepositoryImplementation: JourneyRepository { } public func fetchRecordingJourney(forID id: String) -> RecordingJourney? { - return self.persistent.get(RecordingJourneyDTO.self, forKey: id)?.toDomain() + return self.storage.get(RecordingJourneyDTO.self, forKey: id)?.toDomain() } public func fetchJourneyList(userID: UUID, minCoordinate: Coordinate, maxCoordinate: Coordinate) async -> Result<[Journey], Error> { - #if MOCK +#if MOCK guard let jsonURL = Bundle.module.url(forResource: "MockJourney", withExtension: "json") else { return .failure((MSNetworkError.invalidRouter)) } @@ -83,7 +79,7 @@ public struct JourneyRepositoryImplementation: JourneyRepository { } catch { return .failure(error) } - #else +#else let router = JourneyRouter.checkJourney(userID: userID, minCoordinate: CoordinateDTO(minCoordinate), maxCoordinate: CoordinateDTO(maxCoordinate)) @@ -94,12 +90,12 @@ public struct JourneyRepositoryImplementation: JourneyRepository { case .failure(let error): return .failure(error) } - #endif +#endif } public mutating func startJourney(at coordinate: Coordinate, userID: UUID) async -> Result { - #if MOCK +#if MOCK let recordingJourneyID = "657537c178b6463b9f810371" let recordingJourney = RecordingJourney(id: recordingJourneyID, startTimestamp: .now, @@ -107,7 +103,7 @@ public struct JourneyRepositoryImplementation: JourneyRepository { coordinates: []) self.recordingJourneyID = recordingJourneyID return .success(recordingJourney) - #else +#else let requestDTO = StartJourneyRequestDTO(coordinate: CoordinateDTO(coordinate), startTimestamp: .now, userID: userID) @@ -124,19 +120,19 @@ public struct JourneyRepositoryImplementation: JourneyRepository { self.saveToLocal(value: recordingJourney.startTimestamp) self.recordingJourneyID = recordingJourney.id - #if DEBUG +#if DEBUG if let recordingJourneyID = self.recordingJourneyID { MSLogger.make(category: .userDefaults).debug("기록중인 여정 정보가 저장되었습니다: \(recordingJourneyID)") } else { MSLogger.make(category: .userDefaults).error("기록중인 여정 정보 저장에 실패했습니다.") } - #endif +#endif return .success(recordingJourney) case .failure(let error): return .failure(error) } - #endif +#endif } public func recordJourney(journeyID: String, @@ -149,9 +145,9 @@ public struct JourneyRepositoryImplementation: JourneyRepository { case .success(let responseDTO): let coordinates = responseDTO.coordinates.map { $0.toDomain() } let recordingJourney = RecordingJourney(id: responseDTO.journeyID, - startTimestamp: Date(), - spots: [], - coordinates: coordinates) + startTimestamp: Date(), + spots: [], + coordinates: coordinates) responseDTO.coordinates.forEach { self.saveToLocal(value: $0) } diff --git a/iOS/MSData/Sources/MSData/Repository/Persistable.swift b/iOS/MSData/Sources/MSData/Repository/Persistable.swift index e76e975..15f2127 100644 --- a/iOS/MSData/Sources/MSData/Repository/Persistable.swift +++ b/iOS/MSData/Sources/MSData/Repository/Persistable.swift @@ -8,10 +8,106 @@ import Foundation import MSDomain +import MSLogger +import MSPersistentStorage public protocol Persistable { + var storage: MSPersistentStorage { get } + func saveToLocal(value: Codable) func loadJourneyFromLocal() -> RecordingJourney? } + +// MARK: - KeyStorage + +private struct KeyStorage { + + static var id: String? + static var startTimestamp: String? + static var spots = [String]() + static var coordinates = [String]() + +} + +// MARK: - Default Implementations + +extension Persistable { + + @discardableResult + public func saveToLocal(value: Codable) -> Bool { + let key = UUID().uuidString + self.storage.set(value: value, forKey: key) + + switch value { + case is String: + if KeyStorage.id == nil { + KeyStorage.id = key + } else { + MSLogger.make(category: .persistable).debug("journey ID는 하나의 값만 저장할 수 있습니다.") + return false + } + case is Date: + if KeyStorage.startTimestamp == nil { + KeyStorage.startTimestamp = key + } else { + MSLogger.make(category: .persistable).debug("start tamp는 하나의 값만 저장할 수 있습니다.") + return false + } + case is SpotDTO: + KeyStorage.spots.append(key) + case is CoordinateDTO: + KeyStorage.coordinates.append(key) + default: + MSLogger.make(category: .persistable).debug("RecordingJourney 타입의 요소들만 넣을 수 있습니다.") + return false + } + return true + } + + public func loadJourneyFromLocal() -> RecordingJourney? { + guard let id = self.loadID(), + let startTimestamp = self.loadStartTimeStamp() else { + return nil + } + return RecordingJourney(id: id, + startTimestamp: startTimestamp, + spots: self.loadSpots(), + coordinates: self.loadCoordinates()) + } + + func loadStartTimeStamp() -> Date? { + guard let startTimestampKey = KeyStorage.startTimestamp, + let startTimestamp = self.storage.get(Date.self, forKey: startTimestampKey) + else { + MSLogger.make(category: .persistable).debug("id 또는 startTimestamp가 저장되지 않았습니다.") + return nil + } + return startTimestamp + } + + func loadID() -> String? { + guard let idKey = KeyStorage.id, + let id = self.storage.get(String.self, forKey: idKey) else { + MSLogger.make(category: .persistable).debug("id 또는 startTimestamp가 저장되지 않았습니다.") + return nil + } + return id + } + + func loadSpots() -> [Spot] { + return KeyStorage.spots.compactMap { spotKey in + let spotDTO = self.storage.get(SpotDTO.self, forKey: spotKey) + return spotDTO?.toDomain() + } + } + + func loadCoordinates() -> [Coordinate] { + return KeyStorage.coordinates.compactMap { coordinateKey in + let coordinateDTO = self.storage.get(CoordinateDTO.self, forKey: coordinateKey) + return coordinateDTO?.toDomain() + } + } + +} diff --git a/iOS/MSData/Sources/MSData/Repository/SpotRepository.swift b/iOS/MSData/Sources/MSData/Repository/SpotRepository.swift index c97dad7..07b0fe8 100644 --- a/iOS/MSData/Sources/MSData/Repository/SpotRepository.swift +++ b/iOS/MSData/Sources/MSData/Repository/SpotRepository.swift @@ -10,6 +10,7 @@ import Foundation import MSDomain import MSNetworking import MSLogger +import MSPersistentStorage public protocol SpotRepository: Persistable { @@ -23,11 +24,14 @@ public struct SpotRepositoryImplementation: SpotRepository { // MARK: - Properties private let networking: MSNetworking + public let storage: MSPersistentStorage // MARK: - Initializer - public init(session: URLSession = URLSession(configuration: .default)) { + public init(session: URLSession = URLSession(configuration: .default), + persistentStorage: MSPersistentStorage = FileManagerStorage()) { self.networking = MSNetworking(session: session) + self.storage = persistentStorage } // MARK: - Functions diff --git a/iOS/MSData/Tests/RepositoryTests/PersistableRepositoryTests.swift b/iOS/MSData/Tests/RepositoryTests/PersistableRepositoryTests.swift index 6b296fa..4cdcf5c 100644 --- a/iOS/MSData/Tests/RepositoryTests/PersistableRepositoryTests.swift +++ b/iOS/MSData/Tests/RepositoryTests/PersistableRepositoryTests.swift @@ -1,6 +1,6 @@ // // PersistableRepositoryTests.swift -// +// MSData // // Created by 전민건 on 12/11/23. //