From b39868dd5644390a0b2b7f67a1db786546ba6ce1 Mon Sep 17 00:00:00 2001 From: Dayeon Moon <0217dayun@naver.com> Date: Mon, 18 Mar 2024 00:27:09 +0900 Subject: [PATCH] =?UTF-8?q?[refactor][#21]=20=EC=83=81=EC=84=B8=EC=A0=95?= =?UTF-8?q?=EB=B3=B4=20=EB=A9=94=EB=AA=A8=EB=A6=AC=20=EC=BA=90=EC=8B=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- DontForget.xcodeproj/project.pbxproj | 12 ++++++ .../Sources/Data/Cache/CacheManager.swift | 35 +++++++++++++++ DontForget/Sources/Data/DTO/DTO.swift | 7 +++ .../Data/Service/AnniversaryService.swift | 1 - .../Creation/CreationViewModel.swift | 3 +- .../AnniversaryDetailViewModel.swift | 43 +++++++++++-------- .../Home/ViewModel/HomeViewModel.swift | 2 - 7 files changed, 80 insertions(+), 23 deletions(-) create mode 100644 DontForget/Sources/Data/Cache/CacheManager.swift diff --git a/DontForget.xcodeproj/project.pbxproj b/DontForget.xcodeproj/project.pbxproj index 57cf928..cad7502 100644 --- a/DontForget.xcodeproj/project.pbxproj +++ b/DontForget.xcodeproj/project.pbxproj @@ -55,6 +55,7 @@ AD3B45872B68C288009529DE /* AnniversaryContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = AD3B45862B68C287009529DE /* AnniversaryContentView.swift */; }; AD3B458D2B68DE8F009529DE /* ConfirmView.swift in Sources */ = {isa = PBXBuildFile; fileRef = AD3B458C2B68DE8F009529DE /* ConfirmView.swift */; }; AD6097C62B7CD9C3005060A6 /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = AD6097C52B7CD9C3005060A6 /* GoogleService-Info.plist */; }; + AD7637612BA70887007552E1 /* CacheManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = AD7637602BA70887007552E1 /* CacheManager.swift */; }; AD76D0622B594A5000EFB12E /* UIScreen+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = AD76D0612B594A5000EFB12E /* UIScreen+Extension.swift */; }; AD76D0642B594D2F00EFB12E /* Color+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = AD76D0632B594D2F00EFB12E /* Color+Extension.swift */; }; AD7BEBBC2B91E93B00A03753 /* Pretendard-Medium.otf in Resources */ = {isa = PBXBuildFile; fileRef = AD7BEBB32B91E93A00A03753 /* Pretendard-Medium.otf */; }; @@ -160,6 +161,7 @@ AD3B45862B68C287009529DE /* AnniversaryContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnniversaryContentView.swift; sourceTree = ""; }; AD3B458C2B68DE8F009529DE /* ConfirmView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConfirmView.swift; sourceTree = ""; }; AD6097C52B7CD9C3005060A6 /* GoogleService-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "GoogleService-Info.plist"; sourceTree = ""; }; + AD7637602BA70887007552E1 /* CacheManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CacheManager.swift; sourceTree = ""; }; AD76D0612B594A5000EFB12E /* UIScreen+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIScreen+Extension.swift"; sourceTree = ""; }; AD76D0632B594D2F00EFB12E /* Color+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Color+Extension.swift"; sourceTree = ""; }; AD7BEBB32B91E93A00A03753 /* Pretendard-Medium.otf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Pretendard-Medium.otf"; sourceTree = ""; }; @@ -222,6 +224,7 @@ 09642C342B649A750015220E /* Data */ = { isa = PBXGroup; children = ( + AD76375F2BA70845007552E1 /* Cache */, 09642C5F2B67D2D00015220E /* Error */, 09642C392B649B1D0015220E /* Network */, 09642C592B67CA160015220E /* Repository */, @@ -498,6 +501,14 @@ path = Detail; sourceTree = ""; }; + AD76375F2BA70845007552E1 /* Cache */ = { + isa = PBXGroup; + children = ( + AD7637602BA70887007552E1 /* CacheManager.swift */, + ); + path = Cache; + sourceTree = ""; + }; AD7BEBB22B91E92F00A03753 /* Pretendard */ = { isa = PBXGroup; children = ( @@ -747,6 +758,7 @@ AD147F212B57FF7500561846 /* String+Extension.swift in Sources */, ADA2CC0E2B6CE4CC001A38D9 /* AnniversariesRepository.swift in Sources */, 09642C612B67D2DC0015220E /* ErrorResponse.swift in Sources */, + AD7637612BA70887007552E1 /* CacheManager.swift in Sources */, 09642C4A2B64A37A0015220E /* AnniversaryService.swift in Sources */, 09642C532B67C76F0015220E /* CreationUseCase.swift in Sources */, ADAFFDD52B70C8CC00746D3E /* FetchAnniversaryDetailUseCase.swift in Sources */, diff --git a/DontForget/Sources/Data/Cache/CacheManager.swift b/DontForget/Sources/Data/Cache/CacheManager.swift new file mode 100644 index 0000000..0b6cdf6 --- /dev/null +++ b/DontForget/Sources/Data/Cache/CacheManager.swift @@ -0,0 +1,35 @@ +// +// CacheManager.swift +// DontForget +// +// Created by 제나 on 3/17/24. +// + +import Foundation + +final class CacheManager { + static let shared = CacheManager() + private let cacheDetails = NSCache() + + init() { + cacheDetails.countLimit = 20 + } + + func loadDetail(_ anniversaryId: Int) -> AnniversaryDetail? { + let key = NSString(string: "\(anniversaryId)") + if let cached = cacheDetails.object(forKey: key) { + return cached + } + return nil + } + + func setDetail(_ detail: AnniversaryDetail) { + let key = NSString(string: "\(detail.dto.anniversaryId)") + cacheDetails.setObject(detail, forKey: key) + } + + func removeDetail(_ anniversaryId: Int) { + let key = NSString(string: "\(anniversaryId)") + cacheDetails.removeObject(forKey: key) + } +} diff --git a/DontForget/Sources/Data/DTO/DTO.swift b/DontForget/Sources/Data/DTO/DTO.swift index af3b439..02bb4d1 100644 --- a/DontForget/Sources/Data/DTO/DTO.swift +++ b/DontForget/Sources/Data/DTO/DTO.swift @@ -77,3 +77,10 @@ struct AnniversaryDetailDTO: Decodable { let baseDate: String let baseType: String } + +class AnniversaryDetail { + let dto: AnniversaryDetailDTO + init(anniversaryDetailDTO: AnniversaryDetailDTO) { + self.dto = anniversaryDetailDTO + } +} diff --git a/DontForget/Sources/Data/Service/AnniversaryService.swift b/DontForget/Sources/Data/Service/AnniversaryService.swift index f4cc73f..ec4eb0c 100644 --- a/DontForget/Sources/Data/Service/AnniversaryService.swift +++ b/DontForget/Sources/Data/Service/AnniversaryService.swift @@ -85,7 +85,6 @@ class AnniversaryService { func fetchAnniversaryDetail(anniversaryId: Int) async throws -> AnniversaryDetailResponse { return try await withCheckedThrowingContinuation { continuation in - print("=== DEBUG: fetch detail \(anniversaryId)") provider.request(.readAnniversary(anniversaryId: anniversaryId)) { result in switch result { case let .success(response): diff --git a/DontForget/Sources/Presentations/Application/Creation/CreationViewModel.swift b/DontForget/Sources/Presentations/Application/Creation/CreationViewModel.swift index e656f25..d13efa4 100644 --- a/DontForget/Sources/Presentations/Application/Creation/CreationViewModel.swift +++ b/DontForget/Sources/Presentations/Application/Creation/CreationViewModel.swift @@ -105,10 +105,10 @@ final class CreationViewModel: ViewModelType { } .receive(on: DispatchQueue.main) .sink { completion in + CacheManager.shared.removeDetail(id) self.dismiss = true if case let .failure(error) = completion { self.errorMessage = error.localizedDescription - print("=== \(String(describing: self.errorMessage))") } } receiveValue: { response in self.creationResponse = response @@ -130,7 +130,6 @@ final class CreationViewModel: ViewModelType { ) promise(.success(response)) } catch { - print("=== DEBUG: \(error)") promise(.failure(error)) self.state = .failed("failed fetchAnniversaryDetail()") } diff --git a/DontForget/Sources/Presentations/Application/Detail/ViewModel/AnniversaryDetailViewModel.swift b/DontForget/Sources/Presentations/Application/Detail/ViewModel/AnniversaryDetailViewModel.swift index f910755..71834e2 100644 --- a/DontForget/Sources/Presentations/Application/Detail/ViewModel/AnniversaryDetailViewModel.swift +++ b/DontForget/Sources/Presentations/Application/Detail/ViewModel/AnniversaryDetailViewModel.swift @@ -67,30 +67,37 @@ final class DefaultAnniversaryDetailViewModel: ViewModelType { // MARK: - Method private func fetchAnniversaryDetail() { - Future { promise in - Task { - do { - let response = try await self.fetchAnniversaryDetailUseCase.execute( - requestValue: .init( - query: AnniversaryDetailQuery( - queryId: self.anniversaryId + if let cachedDetail = CacheManager.shared.loadDetail(self.anniversaryId) { + self.anniversaryDetail = cachedDetail.dto + } else { + Future { promise in + Task { + do { + let response = try await self.fetchAnniversaryDetailUseCase.execute( + requestValue: .init( + query: AnniversaryDetailQuery( + queryId: self.anniversaryId + ) ) ) - ) - promise(.success(response)) - } catch { - print("=== DEBUG: \(error)") - promise(.failure(error)) + promise(.success(response)) + } catch { + print("=== DEBUG: \(error)") + promise(.failure(error)) + } } } - } - .receive(on: DispatchQueue.main) - .sink { _ in } receiveValue: { [weak self] response in - if let response = response { - self?.anniversaryDetail = response.anniversaryDetail + .receive(on: DispatchQueue.main) + .sink { _ in } receiveValue: { [weak self] response in + if let response = response { + let detail = response.anniversaryDetail + print("=== DEBUG: fetch detail \(detail.anniversaryId)") + self?.anniversaryDetail = detail + CacheManager.shared.setDetail(AnniversaryDetail(anniversaryDetailDTO: detail)) + } } + .store(in: &cancellables) } - .store(in: &cancellables) } private func deleteAnniversary() { diff --git a/DontForget/Sources/Presentations/Application/Home/ViewModel/HomeViewModel.swift b/DontForget/Sources/Presentations/Application/Home/ViewModel/HomeViewModel.swift index 6015843..137aa24 100644 --- a/DontForget/Sources/Presentations/Application/Home/ViewModel/HomeViewModel.swift +++ b/DontForget/Sources/Presentations/Application/Home/ViewModel/HomeViewModel.swift @@ -82,7 +82,6 @@ final class DefaultHomeViewModel: ViewModelType { .sink { _ in } receiveValue: { [weak self] response in if let self = self, let response = response { self.anniversaries = response.anniversaries.sorted(by: { $0.solarDate < $1.solarDate }) - print("=== DEBUG: \(self.anniversaries)") self.state = .success if !self.anniversaries.isEmpty { self.fetchFirstAnniversaryDetail() @@ -137,7 +136,6 @@ final class DefaultHomeViewModel: ViewModelType { } } let response = try await AnniversaryService.shared.changePushState(status: status) - print("=== DEBUG: changeStatus \(status)") promise(.success(response)) } catch { print("=== DEBUG: changeStatus \(error)")