From 87733cd8f17b3fc805ed40db415d519e0ab08806 Mon Sep 17 00:00:00 2001 From: Song Lee Date: Tue, 14 Sep 2021 16:43:50 +0900 Subject: [PATCH 01/17] =?UTF-8?q?refactor:=20[#191]=20Storage=20=EA=B0=9D?= =?UTF-8?q?=EC=B2=B4=20=EA=B5=AC=EC=A1=B0=ED=99=94=20&=20Data=20Read=20?= =?UTF-8?q?=EC=BD=94=EB=93=9C=20=EA=B0=9C=EC=84=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 데이터 관리 기능을 총괄하는 Storage 객체 신설 - #191에 작성한 구조에 따라 필요한 인터페이스 구축 - 세부 기능은 구현 전, Fake 객체를 사용하여 흐름만 제어 - MainViewModel에서 Auth 인증 후 Data 불러오는 코드 대폭 수정 --- .../project.pbxproj | 22 +++- .../Service/BackUpCenter.swift | 41 +++++++ .../Service/BackUpCenterType.swift | 6 ++ .../Service/CoreDataManagerType.swift | 18 ++++ .../FirebaseStorage/DatabaseManager.swift | 2 +- .../Service/GameStorageType.swift | 16 +++ .../FullStackCodingBot/Service/Storage.swift | 31 ++++++ .../ViewModel/MainViewModel.swift | 100 +++++++----------- 8 files changed, 170 insertions(+), 66 deletions(-) create mode 100644 FullStackCodingBot/FullStackCodingBot/Service/BackUpCenter.swift create mode 100644 FullStackCodingBot/FullStackCodingBot/Service/BackUpCenterType.swift create mode 100644 FullStackCodingBot/FullStackCodingBot/Service/CoreDataManagerType.swift create mode 100644 FullStackCodingBot/FullStackCodingBot/Service/GameStorageType.swift create mode 100644 FullStackCodingBot/FullStackCodingBot/Service/Storage.swift diff --git a/FullStackCodingBot/FullStackCodingBot.xcodeproj/project.pbxproj b/FullStackCodingBot/FullStackCodingBot.xcodeproj/project.pbxproj index 3eb74bf..6efa302 100644 --- a/FullStackCodingBot/FullStackCodingBot.xcodeproj/project.pbxproj +++ b/FullStackCodingBot/FullStackCodingBot.xcodeproj/project.pbxproj @@ -82,6 +82,11 @@ E41C85DA269C4E8F008F2E91 /* PauseViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E41C85D9269C4E8F008F2E91 /* PauseViewController.swift */; }; E41C85DD269C50F0008F2E91 /* PauseViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = E41C85DC269C50F0008F2E91 /* PauseViewModel.swift */; }; E41C85DF269C5149008F2E91 /* PauseButtonController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E41C85DE269C5149008F2E91 /* PauseButtonController.swift */; }; + E4336F5B26F0638A0049A5D8 /* Storage.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4336F5A26F0638A0049A5D8 /* Storage.swift */; }; + E4336F5D26F083650049A5D8 /* GameStorageType.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4336F5C26F083650049A5D8 /* GameStorageType.swift */; }; + E4336F5F26F083840049A5D8 /* BackUpCenterType.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4336F5E26F083840049A5D8 /* BackUpCenterType.swift */; }; + E4336F6126F083A20049A5D8 /* BackUpCenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4336F6026F083A20049A5D8 /* BackUpCenter.swift */; }; + E4336F6326F083C30049A5D8 /* CoreDataManagerType.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4336F6226F083C30049A5D8 /* CoreDataManagerType.swift */; }; E43B64A226ABD81C001D9896 /* GameBackgroundView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E43B64A126ABD81C001D9896 /* GameBackgroundView.swift */; }; E43B64A426AC2384001D9896 /* TimeBarView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E43B64A326AC2384001D9896 /* TimeBarView.swift */; }; E45B0AB82692929F006FDE3D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = E45B0AB72692929F006FDE3D /* Assets.xcassets */; }; @@ -231,6 +236,11 @@ E41C85D9269C4E8F008F2E91 /* PauseViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PauseViewController.swift; sourceTree = ""; }; E41C85DC269C50F0008F2E91 /* PauseViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PauseViewModel.swift; sourceTree = ""; }; E41C85DE269C5149008F2E91 /* PauseButtonController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PauseButtonController.swift; sourceTree = ""; }; + E4336F5A26F0638A0049A5D8 /* Storage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Storage.swift; sourceTree = ""; }; + E4336F5C26F083650049A5D8 /* GameStorageType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GameStorageType.swift; sourceTree = ""; }; + E4336F5E26F083840049A5D8 /* BackUpCenterType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BackUpCenterType.swift; sourceTree = ""; }; + E4336F6026F083A20049A5D8 /* BackUpCenter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BackUpCenter.swift; sourceTree = ""; }; + E4336F6226F083C30049A5D8 /* CoreDataManagerType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CoreDataManagerType.swift; sourceTree = ""; }; E43B64A126ABD81C001D9896 /* GameBackgroundView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GameBackgroundView.swift; sourceTree = ""; }; E43B64A326AC2384001D9896 /* TimeBarView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimeBarView.swift; sourceTree = ""; }; E45B0AAB2692929D006FDE3D /* Full Stack.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Full Stack.app"; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -335,6 +345,11 @@ 715BB20426943CD100286B31 /* Service */ = { isa = PBXGroup; children = ( + E4336F5A26F0638A0049A5D8 /* Storage.swift */, + E4336F5C26F083650049A5D8 /* GameStorageType.swift */, + E4336F6026F083A20049A5D8 /* BackUpCenter.swift */, + E4336F5E26F083840049A5D8 /* BackUpCenterType.swift */, + E4336F6226F083C30049A5D8 /* CoreDataManagerType.swift */, 718F224726C377AA00B2648C /* ErrorManager */, 71BC752C26A940870021BA1A /* DataFormatManager */, 71A5517E26A91C160083A4B0 /* FirebaseStorage */, @@ -381,8 +396,8 @@ 717EAD3A26A656D600E0CDB7 /* PersistenceStorage */ = { isa = PBXGroup; children = ( - E4DF613A26A845670061F6E9 /* AdStorageType.swift */, E4DF613C26A845DA0061F6E9 /* AdStorage.swift */, + E4DF613A26A845670061F6E9 /* AdStorageType.swift */, 71E2B37526AE5E7F00AE496D /* PersistenceStorage.swift */, 71E2B37726AE602200AE496D /* PersistenceStorageType.swift */, ); @@ -1020,6 +1035,7 @@ E4150E9726B8F3E00041DD32 /* TypeWriterView.swift in Sources */, 71310C2C26AA596B00733361 /* CoreDataStorage.xcdatamodeld in Sources */, E4BF710526AFD45A00E8645F /* TimeManagerType.swift in Sources */, + E4336F5F26F083840049A5D8 /* BackUpCenterType.swift in Sources */, 710D0D4F2693F6E500244A16 /* ItemCell.swift in Sources */, E4D7C63E2693E79800D58BA2 /* AppDelegate.swift in Sources */, 715C1C9426BCF9FF0025C681 /* StoryViewController.swift in Sources */, @@ -1032,8 +1048,11 @@ 7165CDDF26957DE400891214 /* GameButtonController.swift in Sources */, 71DF653C2692F90100557693 /* TransitionModel.swift in Sources */, E4BF710726AFD51700E8645F /* FeverManagerType.swift in Sources */, + E4336F6126F083A20049A5D8 /* BackUpCenter.swift in Sources */, + E4336F6326F083C30049A5D8 /* CoreDataManagerType.swift in Sources */, E4BF70FF26AEF3F700E8645F /* GameStatus.swift in Sources */, E4BF712B26B3E6E000E8645F /* AdsInformation.swift in Sources */, + E4336F5B26F0638A0049A5D8 /* Storage.swift in Sources */, E418F37326DC95B800F35AFB /* Color.swift in Sources */, 718F224626C36AE200B2648C /* HowToPlayButtonController.swift in Sources */, E4BF710126AFB0AD00E8645F /* TimeManager.swift in Sources */, @@ -1043,6 +1062,7 @@ 71DF653E2692F92700557693 /* Scene.swift in Sources */, E4BF714326B7E23A00E8645F /* GameSoundEffectStation.swift in Sources */, 71DF64BF2692C1C600557693 /* ItemViewController.swift in Sources */, + E4336F5D26F083650049A5D8 /* GameStorageType.swift in Sources */, 71A5518226A9277C0083A4B0 /* DatabaseManagerType.swift in Sources */, 710A9DAC2692AD5C0090B38A /* MainButtonController.swift in Sources */, E43B64A426AC2384001D9896 /* TimeBarView.swift in Sources */, diff --git a/FullStackCodingBot/FullStackCodingBot/Service/BackUpCenter.swift b/FullStackCodingBot/FullStackCodingBot/Service/BackUpCenter.swift new file mode 100644 index 0000000..9931271 --- /dev/null +++ b/FullStackCodingBot/FullStackCodingBot/Service/BackUpCenter.swift @@ -0,0 +1,41 @@ +import Foundation +import RxSwift + +final class BackUpCenter: BackUpCenterType { + + private var firebaseManager: DatabaseManagerType + private var coreDataManager: CoreDataManagerType + + init(firebaseManager: DatabaseManagerType, coreDataManager: CoreDataManagerType) { + self.firebaseManager = firebaseManager + self.coreDataManager = coreDataManager + } + + func load(with uuid: String?, _ isFirstLaunched: Bool) -> Observable { + Observable.create { [unowned self] observer in + if isFirstLaunched { + self.coreDataManager.create(with: NetworkDTO.empty()) + } + + let localData = self.coreDataManager.read() + + guard let uuid = uuid else { + observer.onNext(localData) + observer.onCompleted() + return Disposables.create() + } + + firebaseManager.getFirebaseData(uuid) + .subscribe { onlineData in + let onlineUpdate = onlineData.date + let localUpdate = localData.date + onlineUpdate > localUpdate ? observer.onNext(onlineData) : observer.onNext(localData) + observer.onCompleted() + } onError: { error in + observer.onError(error) + }.dispose() + + return Disposables.create() + } + } +} diff --git a/FullStackCodingBot/FullStackCodingBot/Service/BackUpCenterType.swift b/FullStackCodingBot/FullStackCodingBot/Service/BackUpCenterType.swift new file mode 100644 index 0000000..8e04b9d --- /dev/null +++ b/FullStackCodingBot/FullStackCodingBot/Service/BackUpCenterType.swift @@ -0,0 +1,6 @@ +import Foundation +import RxSwift + +protocol BackUpCenterType { + func load(with uuid: String?, _ isFirstLaunched: Bool) -> Observable +} diff --git a/FullStackCodingBot/FullStackCodingBot/Service/CoreDataManagerType.swift b/FullStackCodingBot/FullStackCodingBot/Service/CoreDataManagerType.swift new file mode 100644 index 0000000..ae72450 --- /dev/null +++ b/FullStackCodingBot/FullStackCodingBot/Service/CoreDataManagerType.swift @@ -0,0 +1,18 @@ +import Foundation + +protocol CoreDataManagerType { + func create(with initialData: NetworkDTO) + func read() -> NetworkDTO +} + +class FakeCoreDataManager: CoreDataManagerType { + private var data = NetworkDTO.empty() + + func create(with initialData: NetworkDTO) { + self.data = initialData + } + + func read() -> NetworkDTO { + return data + } +} diff --git a/FullStackCodingBot/FullStackCodingBot/Service/FirebaseStorage/DatabaseManager.swift b/FullStackCodingBot/FullStackCodingBot/Service/FirebaseStorage/DatabaseManager.swift index 006b064..e863571 100644 --- a/FullStackCodingBot/FullStackCodingBot/Service/FirebaseStorage/DatabaseManager.swift +++ b/FullStackCodingBot/FullStackCodingBot/Service/FirebaseStorage/DatabaseManager.swift @@ -9,7 +9,7 @@ final class DatabaseManager: DatabaseManagerType { private let disposedBag = DisposeBag() let data = [Unit]() - init(_ ref: DatabaseReference) { + init(_ ref: DatabaseReference = Database.database().reference()) { self.ref = ref } diff --git a/FullStackCodingBot/FullStackCodingBot/Service/GameStorageType.swift b/FullStackCodingBot/FullStackCodingBot/Service/GameStorageType.swift new file mode 100644 index 0000000..41372fe --- /dev/null +++ b/FullStackCodingBot/FullStackCodingBot/Service/GameStorageType.swift @@ -0,0 +1,16 @@ +import Foundation + +protocol GameStorageType { + func update(with data: NetworkDTO) +} + +class FakeGameStorage: GameStorageType { + func update(with data: NetworkDTO) { + /* + ViewModel에서 다음과 같은 코드로 업데이트를 했었다 + storage.update(units: info.units) + storage.raiseMoney(by: info.money) + storage.updateHighScore(new: info.score) + */ + } +} diff --git a/FullStackCodingBot/FullStackCodingBot/Service/Storage.swift b/FullStackCodingBot/FullStackCodingBot/Service/Storage.swift new file mode 100644 index 0000000..f77c86b --- /dev/null +++ b/FullStackCodingBot/FullStackCodingBot/Service/Storage.swift @@ -0,0 +1,31 @@ +import Foundation +import RxSwift + +final class Storage { + + private var gameStorage: GameStorageType + private var adStorage: AdStorageType + private var backUpCenter: BackUpCenterType + + init(gameStorage: GameStorageType, adStorage: AdStorageType, backUpCenter: BackUpCenterType) { + self.gameStorage = gameStorage + self.adStorage = adStorage + self.backUpCenter = backUpCenter + } + + func fill(using uuid: String?, isFirstLaunched: Bool) -> Observable { + Observable.create { [weak self] observer in + self?.backUpCenter.load(with: uuid, isFirstLaunched) + .observe(on: MainScheduler.asyncInstance) + .subscribe(onNext: { data in + self?.gameStorage.update(with: data) + self?.adStorage.setNewRewardsIfPossible(with: data.ads) + }, onError: { _ in + observer.onNext(false) + }, onCompleted: { + observer.onNext(true) + }).dispose() + return Disposables.create() + } + } +} diff --git a/FullStackCodingBot/FullStackCodingBot/ViewModel/MainViewModel.swift b/FullStackCodingBot/FullStackCodingBot/ViewModel/MainViewModel.swift index 52f5cc7..ee1985a 100644 --- a/FullStackCodingBot/FullStackCodingBot/ViewModel/MainViewModel.swift +++ b/FullStackCodingBot/FullStackCodingBot/ViewModel/MainViewModel.swift @@ -14,6 +14,12 @@ final class MainViewModel: AdViewModel { let firebaseDidLoad = BehaviorRelay(value: false) private(set) var rewardAvailable = BehaviorRelay(value: false) + // MARK: 임시 선언 + private var newStorage = Storage(gameStorage: FakeGameStorage(), + adStorage: AdStorage(), + backUpCenter: BackUpCenter(firebaseManager: DatabaseManager(), + coreDataManager: FakeCoreDataManager())) + init(sceneCoordinator: SceneCoordinatorType, storage: PersistenceStorageType, adStorage: AdStorageType, database: DatabaseManagerType, settings: SettingInformation) { self.settingInfo = settings super.init(sceneCoordinator: sceneCoordinator, storage: storage, adStorage: adStorage, database: database) @@ -91,7 +97,7 @@ final class MainViewModel: AdViewModel { } } -// MARK: Login & Load Data +// MARK: Login extension MainViewModel: GKGameCenterControllerDelegate { func gameCenterViewControllerDidFinish(_ gameCenterViewController: GKGameCenterViewController) { @@ -100,12 +106,14 @@ extension MainViewModel: GKGameCenterControllerDelegate { private func setupAppleGameCenterLogin() { GKLocalPlayer.local.authenticateHandler = { [unowned self] gcViewController, error in + guard !self.firebaseDidLoad.value else { return } + if let gcViewController = gcViewController { let scene = Scene.gameCenter(gcViewController) self.sceneCoordinator.transition(to: scene, using: .fullScreen, with: StoryboardType.main, animated: false) } else if let error = error { Firebase.Analytics.logEvent("CancelGameCenter", parameters: ["ErrorMessage": "\(error.localizedDescription)"]) - self.loadOffline() + self.load(with: nil) } else { self.sceneCoordinator.toMain(animated: true) @@ -116,7 +124,7 @@ extension MainViewModel: GKGameCenterControllerDelegate { } guard let credential = credential else { - self.loadOffline() + self.load(with: nil) return } @@ -124,81 +132,45 @@ extension MainViewModel: GKGameCenterControllerDelegate { if let error = error { Firebase.Analytics.logEvent("SignInError", parameters: ["ErrorMessage": "\(error.localizedDescription)"]) - self.loadOffline() + self.load(with: nil) } if let user = user { - loadOnline(user.user.uid) + self.load(with: user.user.uid) } } } } } } - - private func loadOffline() { - loadFromCoredata() - sceneCoordinator.transition(to: .alert(AlertMessage.networkLoad), - using: .alert, - with: .main, - animated: true) - } - - private func loadOnline(_ uuid: String?) { - if !userDefaults.bool(forKey: IdentifierUD.hasLaunchedOnce) { - storage.setupInitialData() - } - loadFromFirebase(uuid) - } - - private func loadFromCoredata() { - switch userDefaults.bool(forKey: IdentifierUD.hasLaunchedOnce) { - case true: - storage.getCoreDataInfo() - case false: - storage.setupInitialData() - } - userDefaults.setValue(true, forKey: IdentifierUD.hasLaunchedOnce) - firebaseDidLoad.accept(true) - } - - private func loadFromFirebase(_ uuid: String?) { - if firebaseDidLoad.value { return } - getUserInformation(uuid) - userDefaults.setValue(true, forKey: IdentifierUD.hasLaunchedOnce) - } - - private func getUserInformation(_ uuid: String?) { - database.getFirebaseData(uuid!) +} + +// MARK: Storage Read +extension MainViewModel { + private func load(with uuid: String?) { + let isFirstLaunched = !userDefaults.bool(forKey: IdentifierUD.hasLaunchedOnce) + + newStorage.fill(using: uuid, isFirstLaunched: isFirstLaunched) .observe(on: MainScheduler.asyncInstance) - .subscribe(onNext: { [unowned self] data in - self.updateDatabaseInformation(data) - self.updateAdInformation(data) - }, onError: { _ in - self.loadFromCoredata() - }, onCompleted: { [unowned self] in - self.firebaseDidLoad.accept(true) + .subscribe(onNext: { [unowned self] isLoaded in + self.firebaseDidLoad.accept(isLoaded) }).disposed(by: rx.disposeBag) - } - - private func updateDatabaseInformation(_ info: NetworkDTO) { - let firebaseUpdate = info.date - let coredataUpdate = storage.lastUpdated() - guard firebaseUpdate > coredataUpdate else { - loadFromCoredata() - return - } + markAsLauncedOnce() - storage.update(units: info.units) - storage.raiseMoney(by: info.money) - storage.updateHighScore(new: info.score) + if uuid == nil { + showNetworkAlert() + } + } + + private func markAsLauncedOnce() { + userDefaults.setValue(true, forKey: IdentifierUD.hasLaunchedOnce) } - private func updateAdInformation(_ info: NetworkDTO) { - adStorage.setNewRewardsIfPossible(with: info.ads) - .subscribe(onError: { error in - Firebase.Analytics.logEvent("RewardsError", parameters: ["ErrorMessage": "\(error)"])}) - .disposed(by: rx.disposeBag) + private func showNetworkAlert() { + sceneCoordinator.transition(to: .alert(AlertMessage.networkLoad), + using: .alert, + with: .main, + animated: true) } } From 2a2997ad218e2c033c6d4030b82a75db18c02849 Mon Sep 17 00:00:00 2001 From: Song Lee Date: Tue, 14 Sep 2021 16:48:47 +0900 Subject: [PATCH 02/17] =?UTF-8?q?refactor:=20[#191]=20=EA=B0=9D=EC=B2=B4?= =?UTF-8?q?=20=EC=9D=B4=EB=A6=84=20=EB=B3=80=EA=B2=BD,=20=EB=94=94?= =?UTF-8?q?=EB=A0=89=ED=86=A0=EB=A6=AC=20=EC=B2=B4=EA=B3=84=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../project.pbxproj | 82 ++++++++++--------- .../AppCycle/AppDelegate.swift | 6 +- .../FeverManager.swift | 0 .../FeverManagerType.swift | 0 .../GameUnitManager.swift | 0 .../GameUnitManagerType.swift | 0 .../TimeManager.swift | 0 .../TimeManagerType.swift | 0 .../BackUpManager}/BackUpCenter.swift | 4 +- .../BackUpManager}/BackUpCenterType.swift | 0 .../BackUpManager}/CoreDataManagerType.swift | 0 .../BackUpManager/FirebaseManager.swift} | 2 +- .../BackUpManager/FirebaseManagerType.swift} | 2 +- .../RealDataStorage}/AdStorage.swift | 0 .../RealDataStorage}/AdStorageType.swift | 0 .../RealDataStorage}/GameStorageType.swift | 0 .../RealDataStorage}/PersistenceStorage.swift | 0 .../PersistenceStorageType.swift | 0 .../Service/{ => Storage}/Storage.swift | 0 .../ViewModel/AdViewModel.swift | 2 +- .../ViewModel/CommonViewModel.swift | 4 +- .../ViewModel/GameOverViewModel.swift | 2 +- .../ViewModel/GameViewModel.swift | 2 +- .../ViewModel/HowToPlayViewModel.swift | 2 +- .../ViewModel/ItemViewModel.swift | 2 +- .../ViewModel/MainViewModel.swift | 4 +- .../ViewModel/PauseViewModel.swift | 2 +- .../ViewModel/RankViewModel.swift | 2 +- .../ViewModel/ShopViewModel.swift | 2 +- .../ViewModel/StoryViewModel.swift | 2 +- 30 files changed, 65 insertions(+), 57 deletions(-) rename FullStackCodingBot/FullStackCodingBot/Service/{GameManager => GameLogic}/FeverManager.swift (100%) rename FullStackCodingBot/FullStackCodingBot/Service/{GameManager => GameLogic}/FeverManagerType.swift (100%) rename FullStackCodingBot/FullStackCodingBot/Service/{GameManager => GameLogic}/GameUnitManager.swift (100%) rename FullStackCodingBot/FullStackCodingBot/Service/{GameManager => GameLogic}/GameUnitManagerType.swift (100%) rename FullStackCodingBot/FullStackCodingBot/Service/{GameManager => GameLogic}/TimeManager.swift (100%) rename FullStackCodingBot/FullStackCodingBot/Service/{GameManager => GameLogic}/TimeManagerType.swift (100%) rename FullStackCodingBot/FullStackCodingBot/Service/{ => Storage/BackUpManager}/BackUpCenter.swift (92%) rename FullStackCodingBot/FullStackCodingBot/Service/{ => Storage/BackUpManager}/BackUpCenterType.swift (100%) rename FullStackCodingBot/FullStackCodingBot/Service/{ => Storage/BackUpManager}/CoreDataManagerType.swift (100%) rename FullStackCodingBot/FullStackCodingBot/Service/{FirebaseStorage/DatabaseManager.swift => Storage/BackUpManager/FirebaseManager.swift} (97%) rename FullStackCodingBot/FullStackCodingBot/Service/{FirebaseStorage/DatabaseManagerType.swift => Storage/BackUpManager/FirebaseManagerType.swift} (85%) rename FullStackCodingBot/FullStackCodingBot/Service/{PersistenceStorage => Storage/RealDataStorage}/AdStorage.swift (100%) rename FullStackCodingBot/FullStackCodingBot/Service/{PersistenceStorage => Storage/RealDataStorage}/AdStorageType.swift (100%) rename FullStackCodingBot/FullStackCodingBot/Service/{ => Storage/RealDataStorage}/GameStorageType.swift (100%) rename FullStackCodingBot/FullStackCodingBot/Service/{PersistenceStorage => Storage/RealDataStorage}/PersistenceStorage.swift (100%) rename FullStackCodingBot/FullStackCodingBot/Service/{PersistenceStorage => Storage/RealDataStorage}/PersistenceStorageType.swift (100%) rename FullStackCodingBot/FullStackCodingBot/Service/{ => Storage}/Storage.swift (100%) diff --git a/FullStackCodingBot/FullStackCodingBot.xcodeproj/project.pbxproj b/FullStackCodingBot/FullStackCodingBot.xcodeproj/project.pbxproj index 6efa302..0a38903 100644 --- a/FullStackCodingBot/FullStackCodingBot.xcodeproj/project.pbxproj +++ b/FullStackCodingBot/FullStackCodingBot.xcodeproj/project.pbxproj @@ -41,8 +41,8 @@ 719A6A9B26B11208006AC991 /* NetworkDTO.swift in Sources */ = {isa = PBXBuildFile; fileRef = 719A6A9A26B11208006AC991 /* NetworkDTO.swift */; }; 719AB9DE26B7ADF2001B5913 /* SettingViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 719AB9DD26B7ADF2001B5913 /* SettingViewController.swift */; }; 719DA2B126A7FC9900624C61 /* JoystixMonospace-Regular.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 719DA2B026A7FC9800624C61 /* JoystixMonospace-Regular.ttf */; }; - 71A5518026A91C280083A4B0 /* DatabaseManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 71A5517F26A91C280083A4B0 /* DatabaseManager.swift */; }; - 71A5518226A9277C0083A4B0 /* DatabaseManagerType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 71A5518126A9277C0083A4B0 /* DatabaseManagerType.swift */; }; + 71A5518026A91C280083A4B0 /* FirebaseManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 71A5517F26A91C280083A4B0 /* FirebaseManager.swift */; }; + 71A5518226A9277C0083A4B0 /* FirebaseManagerType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 71A5518126A9277C0083A4B0 /* FirebaseManagerType.swift */; }; 71BC752E26A940A10021BA1A /* DataFormatManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 71BC752D26A940A10021BA1A /* DataFormatManager.swift */; }; 71DF64B92692C13A00557693 /* ShopViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 71DF64B82692C13A00557693 /* ShopViewController.swift */; }; 71DF64BD2692C18F00557693 /* RankViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 71DF64BC2692C18F00557693 /* RankViewController.swift */; }; @@ -196,8 +196,8 @@ 719A6A9A26B11208006AC991 /* NetworkDTO.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NetworkDTO.swift; sourceTree = ""; }; 719AB9DD26B7ADF2001B5913 /* SettingViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingViewController.swift; sourceTree = ""; }; 719DA2B026A7FC9800624C61 /* JoystixMonospace-Regular.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "JoystixMonospace-Regular.ttf"; sourceTree = ""; }; - 71A5517F26A91C280083A4B0 /* DatabaseManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DatabaseManager.swift; sourceTree = ""; }; - 71A5518126A9277C0083A4B0 /* DatabaseManagerType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DatabaseManagerType.swift; sourceTree = ""; }; + 71A5517F26A91C280083A4B0 /* FirebaseManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FirebaseManager.swift; sourceTree = ""; }; + 71A5518126A9277C0083A4B0 /* FirebaseManagerType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FirebaseManagerType.swift; sourceTree = ""; }; 71BC752D26A940A10021BA1A /* DataFormatManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DataFormatManager.swift; sourceTree = ""; }; 71DF64B82692C13A00557693 /* ShopViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShopViewController.swift; sourceTree = ""; }; 71DF64BC2692C18F00557693 /* RankViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RankViewController.swift; sourceTree = ""; }; @@ -345,16 +345,10 @@ 715BB20426943CD100286B31 /* Service */ = { isa = PBXGroup; children = ( - E4336F5A26F0638A0049A5D8 /* Storage.swift */, - E4336F5C26F083650049A5D8 /* GameStorageType.swift */, - E4336F6026F083A20049A5D8 /* BackUpCenter.swift */, - E4336F5E26F083840049A5D8 /* BackUpCenterType.swift */, - E4336F6226F083C30049A5D8 /* CoreDataManagerType.swift */, - 718F224726C377AA00B2648C /* ErrorManager */, + E4336F6426F08A8D0049A5D8 /* Storage */, + 717EAD3B26A656E200E0CDB7 /* GameLogic */, 71BC752C26A940870021BA1A /* DataFormatManager */, - 71A5517E26A91C160083A4B0 /* FirebaseStorage */, - 717EAD3B26A656E200E0CDB7 /* GameManager */, - 717EAD3A26A656D600E0CDB7 /* PersistenceStorage */, + 718F224726C377AA00B2648C /* ErrorManager */, ); path = Service; sourceTree = ""; @@ -393,18 +387,7 @@ path = HowToPlay; sourceTree = ""; }; - 717EAD3A26A656D600E0CDB7 /* PersistenceStorage */ = { - isa = PBXGroup; - children = ( - E4DF613C26A845DA0061F6E9 /* AdStorage.swift */, - E4DF613A26A845670061F6E9 /* AdStorageType.swift */, - 71E2B37526AE5E7F00AE496D /* PersistenceStorage.swift */, - 71E2B37726AE602200AE496D /* PersistenceStorageType.swift */, - ); - path = PersistenceStorage; - sourceTree = ""; - }; - 717EAD3B26A656E200E0CDB7 /* GameManager */ = { + 717EAD3B26A656E200E0CDB7 /* GameLogic */ = { isa = PBXGroup; children = ( E41C85D7269C252D008F2E91 /* GameUnitManagerType.swift */, @@ -414,7 +397,7 @@ E4BF710626AFD51700E8645F /* FeverManagerType.swift */, E4BF710226AFCC7500E8645F /* FeverManager.swift */, ); - path = GameManager; + path = GameLogic; sourceTree = ""; }; 717EAD3C26A6576600E0CDB7 /* Button */ = { @@ -447,15 +430,6 @@ path = ErrorManager; sourceTree = ""; }; - 71A5517E26A91C160083A4B0 /* FirebaseStorage */ = { - isa = PBXGroup; - children = ( - 71A5517F26A91C280083A4B0 /* DatabaseManager.swift */, - 71A5518126A9277C0083A4B0 /* DatabaseManagerType.swift */, - ); - path = FirebaseStorage; - sourceTree = ""; - }; 71BC752C26A940870021BA1A /* DataFormatManager */ = { isa = PBXGroup; children = ( @@ -652,6 +626,40 @@ path = Reward; sourceTree = ""; }; + E4336F6426F08A8D0049A5D8 /* Storage */ = { + isa = PBXGroup; + children = ( + E4336F5A26F0638A0049A5D8 /* Storage.swift */, + E4336F6526F08AD80049A5D8 /* RealDataStorage */, + E4336F6626F08AF10049A5D8 /* BackUpManager */, + ); + path = Storage; + sourceTree = ""; + }; + E4336F6526F08AD80049A5D8 /* RealDataStorage */ = { + isa = PBXGroup; + children = ( + E4DF613C26A845DA0061F6E9 /* AdStorage.swift */, + E4DF613A26A845670061F6E9 /* AdStorageType.swift */, + E4336F5C26F083650049A5D8 /* GameStorageType.swift */, + 71E2B37526AE5E7F00AE496D /* PersistenceStorage.swift */, + 71E2B37726AE602200AE496D /* PersistenceStorageType.swift */, + ); + path = RealDataStorage; + sourceTree = ""; + }; + E4336F6626F08AF10049A5D8 /* BackUpManager */ = { + isa = PBXGroup; + children = ( + E4336F6026F083A20049A5D8 /* BackUpCenter.swift */, + E4336F5E26F083840049A5D8 /* BackUpCenterType.swift */, + E4336F6226F083C30049A5D8 /* CoreDataManagerType.swift */, + 71A5517F26A91C280083A4B0 /* FirebaseManager.swift */, + 71A5518126A9277C0083A4B0 /* FirebaseManagerType.swift */, + ); + path = BackUpManager; + sourceTree = ""; + }; E45B0AA22692929C006FDE3D = { isa = PBXGroup; children = ( @@ -1043,7 +1051,7 @@ E45B0AC72692F42D006FDE3D /* UnitPerspectiveView.swift in Sources */, E41C85D4269BFB84008F2E91 /* GameUnitManager.swift in Sources */, E418F36A26DB5D8000F35AFB /* RewardPopupView.swift in Sources */, - 71A5518026A91C280083A4B0 /* DatabaseManager.swift in Sources */, + 71A5518026A91C280083A4B0 /* FirebaseManager.swift in Sources */, E4779C6926983F8000B92D24 /* GameOverViewModel.swift in Sources */, 7165CDDF26957DE400891214 /* GameButtonController.swift in Sources */, 71DF653C2692F90100557693 /* TransitionModel.swift in Sources */, @@ -1063,7 +1071,7 @@ E4BF714326B7E23A00E8645F /* GameSoundEffectStation.swift in Sources */, 71DF64BF2692C1C600557693 /* ItemViewController.swift in Sources */, E4336F5D26F083650049A5D8 /* GameStorageType.swift in Sources */, - 71A5518226A9277C0083A4B0 /* DatabaseManagerType.swift in Sources */, + 71A5518226A9277C0083A4B0 /* FirebaseManagerType.swift in Sources */, 710A9DAC2692AD5C0090B38A /* MainButtonController.swift in Sources */, E43B64A426AC2384001D9896 /* TimeBarView.swift in Sources */, E4150EA426BE9A540041DD32 /* Line.swift in Sources */, diff --git a/FullStackCodingBot/FullStackCodingBot/AppCycle/AppDelegate.swift b/FullStackCodingBot/FullStackCodingBot/AppCycle/AppDelegate.swift index 602deab..016762a 100644 --- a/FullStackCodingBot/FullStackCodingBot/AppCycle/AppDelegate.swift +++ b/FullStackCodingBot/FullStackCodingBot/AppCycle/AppDelegate.swift @@ -20,7 +20,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate { } func applicationDidEnterBackground(_ application: UIApplication) { - let database = DatabaseManager(Database.database().reference()) + let database = FirebaseManager(Database.database().reference()) let networkDTO = NetworkDTO(units: storage.itemList(), money: storage.myMoney(), score: storage.myHighScore(), ads: adStorage.currentInformation(), date: Date()) if storage.itemList().isEmpty { return } database.updateDatabase(networkDTO) @@ -45,7 +45,7 @@ private extension AppDelegate { let hasLaunchedOnce = userDefaults.bool(forKey: IdentifierUD.hasLaunchedOnce) let settings = getSettingInformation(hasLaunchedOnce) let coordinator = SceneCoordinator(window: window!) - let database = DatabaseManager(Database.database().reference()) + let database = FirebaseManager(Database.database().reference()) let scene = getFirstScene(hasLaunchedOnce, coordinator, database, settings) coordinator.transition(to: scene, using: .root, with: StoryboardType.main, animated: false) } @@ -58,7 +58,7 @@ private extension AppDelegate { private func getFirstScene(_ hasLaunchedOnce: Bool, _ sceneCoordinator: SceneCoordinator, - _ database: DatabaseManager, + _ database: FirebaseManager, _ settings: SettingInformation) -> Scene { switch hasLaunchedOnce { diff --git a/FullStackCodingBot/FullStackCodingBot/Service/GameManager/FeverManager.swift b/FullStackCodingBot/FullStackCodingBot/Service/GameLogic/FeverManager.swift similarity index 100% rename from FullStackCodingBot/FullStackCodingBot/Service/GameManager/FeverManager.swift rename to FullStackCodingBot/FullStackCodingBot/Service/GameLogic/FeverManager.swift diff --git a/FullStackCodingBot/FullStackCodingBot/Service/GameManager/FeverManagerType.swift b/FullStackCodingBot/FullStackCodingBot/Service/GameLogic/FeverManagerType.swift similarity index 100% rename from FullStackCodingBot/FullStackCodingBot/Service/GameManager/FeverManagerType.swift rename to FullStackCodingBot/FullStackCodingBot/Service/GameLogic/FeverManagerType.swift diff --git a/FullStackCodingBot/FullStackCodingBot/Service/GameManager/GameUnitManager.swift b/FullStackCodingBot/FullStackCodingBot/Service/GameLogic/GameUnitManager.swift similarity index 100% rename from FullStackCodingBot/FullStackCodingBot/Service/GameManager/GameUnitManager.swift rename to FullStackCodingBot/FullStackCodingBot/Service/GameLogic/GameUnitManager.swift diff --git a/FullStackCodingBot/FullStackCodingBot/Service/GameManager/GameUnitManagerType.swift b/FullStackCodingBot/FullStackCodingBot/Service/GameLogic/GameUnitManagerType.swift similarity index 100% rename from FullStackCodingBot/FullStackCodingBot/Service/GameManager/GameUnitManagerType.swift rename to FullStackCodingBot/FullStackCodingBot/Service/GameLogic/GameUnitManagerType.swift diff --git a/FullStackCodingBot/FullStackCodingBot/Service/GameManager/TimeManager.swift b/FullStackCodingBot/FullStackCodingBot/Service/GameLogic/TimeManager.swift similarity index 100% rename from FullStackCodingBot/FullStackCodingBot/Service/GameManager/TimeManager.swift rename to FullStackCodingBot/FullStackCodingBot/Service/GameLogic/TimeManager.swift diff --git a/FullStackCodingBot/FullStackCodingBot/Service/GameManager/TimeManagerType.swift b/FullStackCodingBot/FullStackCodingBot/Service/GameLogic/TimeManagerType.swift similarity index 100% rename from FullStackCodingBot/FullStackCodingBot/Service/GameManager/TimeManagerType.swift rename to FullStackCodingBot/FullStackCodingBot/Service/GameLogic/TimeManagerType.swift diff --git a/FullStackCodingBot/FullStackCodingBot/Service/BackUpCenter.swift b/FullStackCodingBot/FullStackCodingBot/Service/Storage/BackUpManager/BackUpCenter.swift similarity index 92% rename from FullStackCodingBot/FullStackCodingBot/Service/BackUpCenter.swift rename to FullStackCodingBot/FullStackCodingBot/Service/Storage/BackUpManager/BackUpCenter.swift index 9931271..c586bf8 100644 --- a/FullStackCodingBot/FullStackCodingBot/Service/BackUpCenter.swift +++ b/FullStackCodingBot/FullStackCodingBot/Service/Storage/BackUpManager/BackUpCenter.swift @@ -3,10 +3,10 @@ import RxSwift final class BackUpCenter: BackUpCenterType { - private var firebaseManager: DatabaseManagerType + private var firebaseManager: FirebaseManagerType private var coreDataManager: CoreDataManagerType - init(firebaseManager: DatabaseManagerType, coreDataManager: CoreDataManagerType) { + init(firebaseManager: FirebaseManagerType, coreDataManager: CoreDataManagerType) { self.firebaseManager = firebaseManager self.coreDataManager = coreDataManager } diff --git a/FullStackCodingBot/FullStackCodingBot/Service/BackUpCenterType.swift b/FullStackCodingBot/FullStackCodingBot/Service/Storage/BackUpManager/BackUpCenterType.swift similarity index 100% rename from FullStackCodingBot/FullStackCodingBot/Service/BackUpCenterType.swift rename to FullStackCodingBot/FullStackCodingBot/Service/Storage/BackUpManager/BackUpCenterType.swift diff --git a/FullStackCodingBot/FullStackCodingBot/Service/CoreDataManagerType.swift b/FullStackCodingBot/FullStackCodingBot/Service/Storage/BackUpManager/CoreDataManagerType.swift similarity index 100% rename from FullStackCodingBot/FullStackCodingBot/Service/CoreDataManagerType.swift rename to FullStackCodingBot/FullStackCodingBot/Service/Storage/BackUpManager/CoreDataManagerType.swift diff --git a/FullStackCodingBot/FullStackCodingBot/Service/FirebaseStorage/DatabaseManager.swift b/FullStackCodingBot/FullStackCodingBot/Service/Storage/BackUpManager/FirebaseManager.swift similarity index 97% rename from FullStackCodingBot/FullStackCodingBot/Service/FirebaseStorage/DatabaseManager.swift rename to FullStackCodingBot/FullStackCodingBot/Service/Storage/BackUpManager/FirebaseManager.swift index e863571..0aab4f2 100644 --- a/FullStackCodingBot/FullStackCodingBot/Service/FirebaseStorage/DatabaseManager.swift +++ b/FullStackCodingBot/FullStackCodingBot/Service/Storage/BackUpManager/FirebaseManager.swift @@ -2,7 +2,7 @@ import Foundation import RxSwift import Firebase -final class DatabaseManager: DatabaseManagerType { +final class FirebaseManager: FirebaseManagerType { private var ref: DatabaseReference private let uid = Auth.auth().currentUser?.uid ?? "" diff --git a/FullStackCodingBot/FullStackCodingBot/Service/FirebaseStorage/DatabaseManagerType.swift b/FullStackCodingBot/FullStackCodingBot/Service/Storage/BackUpManager/FirebaseManagerType.swift similarity index 85% rename from FullStackCodingBot/FullStackCodingBot/Service/FirebaseStorage/DatabaseManagerType.swift rename to FullStackCodingBot/FullStackCodingBot/Service/Storage/BackUpManager/FirebaseManagerType.swift index f8c6cbe..6a3a892 100644 --- a/FullStackCodingBot/FullStackCodingBot/Service/FirebaseStorage/DatabaseManagerType.swift +++ b/FullStackCodingBot/FullStackCodingBot/Service/Storage/BackUpManager/FirebaseManagerType.swift @@ -1,7 +1,7 @@ import Foundation import RxSwift -protocol DatabaseManagerType { +protocol FirebaseManagerType { @discardableResult func getFirebaseData(_ uuid: String) -> Observable diff --git a/FullStackCodingBot/FullStackCodingBot/Service/PersistenceStorage/AdStorage.swift b/FullStackCodingBot/FullStackCodingBot/Service/Storage/RealDataStorage/AdStorage.swift similarity index 100% rename from FullStackCodingBot/FullStackCodingBot/Service/PersistenceStorage/AdStorage.swift rename to FullStackCodingBot/FullStackCodingBot/Service/Storage/RealDataStorage/AdStorage.swift diff --git a/FullStackCodingBot/FullStackCodingBot/Service/PersistenceStorage/AdStorageType.swift b/FullStackCodingBot/FullStackCodingBot/Service/Storage/RealDataStorage/AdStorageType.swift similarity index 100% rename from FullStackCodingBot/FullStackCodingBot/Service/PersistenceStorage/AdStorageType.swift rename to FullStackCodingBot/FullStackCodingBot/Service/Storage/RealDataStorage/AdStorageType.swift diff --git a/FullStackCodingBot/FullStackCodingBot/Service/GameStorageType.swift b/FullStackCodingBot/FullStackCodingBot/Service/Storage/RealDataStorage/GameStorageType.swift similarity index 100% rename from FullStackCodingBot/FullStackCodingBot/Service/GameStorageType.swift rename to FullStackCodingBot/FullStackCodingBot/Service/Storage/RealDataStorage/GameStorageType.swift diff --git a/FullStackCodingBot/FullStackCodingBot/Service/PersistenceStorage/PersistenceStorage.swift b/FullStackCodingBot/FullStackCodingBot/Service/Storage/RealDataStorage/PersistenceStorage.swift similarity index 100% rename from FullStackCodingBot/FullStackCodingBot/Service/PersistenceStorage/PersistenceStorage.swift rename to FullStackCodingBot/FullStackCodingBot/Service/Storage/RealDataStorage/PersistenceStorage.swift diff --git a/FullStackCodingBot/FullStackCodingBot/Service/PersistenceStorage/PersistenceStorageType.swift b/FullStackCodingBot/FullStackCodingBot/Service/Storage/RealDataStorage/PersistenceStorageType.swift similarity index 100% rename from FullStackCodingBot/FullStackCodingBot/Service/PersistenceStorage/PersistenceStorageType.swift rename to FullStackCodingBot/FullStackCodingBot/Service/Storage/RealDataStorage/PersistenceStorageType.swift diff --git a/FullStackCodingBot/FullStackCodingBot/Service/Storage.swift b/FullStackCodingBot/FullStackCodingBot/Service/Storage/Storage.swift similarity index 100% rename from FullStackCodingBot/FullStackCodingBot/Service/Storage.swift rename to FullStackCodingBot/FullStackCodingBot/Service/Storage/Storage.swift diff --git a/FullStackCodingBot/FullStackCodingBot/ViewModel/AdViewModel.swift b/FullStackCodingBot/FullStackCodingBot/ViewModel/AdViewModel.swift index f41c748..6af6e65 100644 --- a/FullStackCodingBot/FullStackCodingBot/ViewModel/AdViewModel.swift +++ b/FullStackCodingBot/FullStackCodingBot/ViewModel/AdViewModel.swift @@ -4,7 +4,7 @@ class AdViewModel: CommonViewModel { let adStorage: AdStorageType - init(sceneCoordinator: SceneCoordinatorType, storage: PersistenceStorageType, adStorage: AdStorageType, database: DatabaseManagerType) { + init(sceneCoordinator: SceneCoordinatorType, storage: PersistenceStorageType, adStorage: AdStorageType, database: FirebaseManagerType) { self.adStorage = adStorage super.init(sceneCoordinator: sceneCoordinator, storage: storage, database: database) } diff --git a/FullStackCodingBot/FullStackCodingBot/ViewModel/CommonViewModel.swift b/FullStackCodingBot/FullStackCodingBot/ViewModel/CommonViewModel.swift index 96f87d7..3aaf3b7 100644 --- a/FullStackCodingBot/FullStackCodingBot/ViewModel/CommonViewModel.swift +++ b/FullStackCodingBot/FullStackCodingBot/ViewModel/CommonViewModel.swift @@ -4,9 +4,9 @@ class CommonViewModel: NSObject { let sceneCoordinator: SceneCoordinatorType let storage: PersistenceStorageType - let database: DatabaseManagerType + let database: FirebaseManagerType - init(sceneCoordinator: SceneCoordinatorType, storage: PersistenceStorageType, database: DatabaseManagerType) { + init(sceneCoordinator: SceneCoordinatorType, storage: PersistenceStorageType, database: FirebaseManagerType) { self.sceneCoordinator = sceneCoordinator self.storage = storage self.database = database diff --git a/FullStackCodingBot/FullStackCodingBot/ViewModel/GameOverViewModel.swift b/FullStackCodingBot/FullStackCodingBot/ViewModel/GameOverViewModel.swift index 80b34f2..e194dc1 100644 --- a/FullStackCodingBot/FullStackCodingBot/ViewModel/GameOverViewModel.swift +++ b/FullStackCodingBot/FullStackCodingBot/ViewModel/GameOverViewModel.swift @@ -28,7 +28,7 @@ final class GameOverViewModel: CommonViewModel { init(sceneCoordinator: SceneCoordinatorType, storage: PersistenceStorageType, - database: DatabaseManagerType, + database: FirebaseManagerType, finalScore: Int, newGameStatus: BehaviorRelay, gameStoryManager: GameStoryManager = GameStoryManager()) { diff --git a/FullStackCodingBot/FullStackCodingBot/ViewModel/GameViewModel.swift b/FullStackCodingBot/FullStackCodingBot/ViewModel/GameViewModel.swift index cb1fd14..cbf0bde 100644 --- a/FullStackCodingBot/FullStackCodingBot/ViewModel/GameViewModel.swift +++ b/FullStackCodingBot/FullStackCodingBot/ViewModel/GameViewModel.swift @@ -34,7 +34,7 @@ final class GameViewModel: CommonViewModel { init(sceneCoordinator: SceneCoordinatorType, storage: PersistenceStorageType, - database: DatabaseManagerType, + database: FirebaseManagerType, pauseAction: CocoaAction? = nil, gameUnitManager: GameUnitManagerType, timeManager: TimeManagerType = TimeManager(), diff --git a/FullStackCodingBot/FullStackCodingBot/ViewModel/HowToPlayViewModel.swift b/FullStackCodingBot/FullStackCodingBot/ViewModel/HowToPlayViewModel.swift index fe25d1f..519c63e 100644 --- a/FullStackCodingBot/FullStackCodingBot/ViewModel/HowToPlayViewModel.swift +++ b/FullStackCodingBot/FullStackCodingBot/ViewModel/HowToPlayViewModel.swift @@ -12,7 +12,7 @@ final class HowToPlayViewModel: CommonViewModel { init(sceneCoordinator: SceneCoordinatorType, storage: PersistenceStorageType, adStorage: AdStorageType, - database: DatabaseManagerType, + database: FirebaseManagerType, cancelAction: CocoaAction? = nil) { self.cancelAction = CocoaAction { diff --git a/FullStackCodingBot/FullStackCodingBot/ViewModel/ItemViewModel.swift b/FullStackCodingBot/FullStackCodingBot/ViewModel/ItemViewModel.swift index 22f7b77..587c453 100644 --- a/FullStackCodingBot/FullStackCodingBot/ViewModel/ItemViewModel.swift +++ b/FullStackCodingBot/FullStackCodingBot/ViewModel/ItemViewModel.swift @@ -26,7 +26,7 @@ final class ItemViewModel: CommonViewModel { init(sceneCoordinator: SceneCoordinatorType, storage: PersistenceStorageType, - database: DatabaseManagerType, + database: FirebaseManagerType, cancelAction: CocoaAction? = nil, soundEffectType: MainSoundEffect = .upgrade) { self.cancelAction = CocoaAction { diff --git a/FullStackCodingBot/FullStackCodingBot/ViewModel/MainViewModel.swift b/FullStackCodingBot/FullStackCodingBot/ViewModel/MainViewModel.swift index ee1985a..68655db 100644 --- a/FullStackCodingBot/FullStackCodingBot/ViewModel/MainViewModel.swift +++ b/FullStackCodingBot/FullStackCodingBot/ViewModel/MainViewModel.swift @@ -17,10 +17,10 @@ final class MainViewModel: AdViewModel { // MARK: 임시 선언 private var newStorage = Storage(gameStorage: FakeGameStorage(), adStorage: AdStorage(), - backUpCenter: BackUpCenter(firebaseManager: DatabaseManager(), + backUpCenter: BackUpCenter(firebaseManager: FirebaseManager(), coreDataManager: FakeCoreDataManager())) - init(sceneCoordinator: SceneCoordinatorType, storage: PersistenceStorageType, adStorage: AdStorageType, database: DatabaseManagerType, settings: SettingInformation) { + init(sceneCoordinator: SceneCoordinatorType, storage: PersistenceStorageType, adStorage: AdStorageType, database: FirebaseManagerType, settings: SettingInformation) { self.settingInfo = settings super.init(sceneCoordinator: sceneCoordinator, storage: storage, adStorage: adStorage, database: database) diff --git a/FullStackCodingBot/FullStackCodingBot/ViewModel/PauseViewModel.swift b/FullStackCodingBot/FullStackCodingBot/ViewModel/PauseViewModel.swift index aa857e9..72de88f 100644 --- a/FullStackCodingBot/FullStackCodingBot/ViewModel/PauseViewModel.swift +++ b/FullStackCodingBot/FullStackCodingBot/ViewModel/PauseViewModel.swift @@ -11,7 +11,7 @@ final class PauseViewModel: CommonViewModel { return currentScore.map {String($0)}.asDriver(onErrorJustReturn: "") }() - init(sceneCoordinator: SceneCoordinatorType, storage: PersistenceStorageType, database: DatabaseManagerType, currentScore: Int, newGameStatus: BehaviorRelay) { + init(sceneCoordinator: SceneCoordinatorType, storage: PersistenceStorageType, database: FirebaseManagerType, currentScore: Int, newGameStatus: BehaviorRelay) { self.newGameStatus = newGameStatus self.currentScore.accept(currentScore) super.init(sceneCoordinator: sceneCoordinator, storage: storage, database: database) diff --git a/FullStackCodingBot/FullStackCodingBot/ViewModel/RankViewModel.swift b/FullStackCodingBot/FullStackCodingBot/ViewModel/RankViewModel.swift index ff1bdca..2617baf 100644 --- a/FullStackCodingBot/FullStackCodingBot/ViewModel/RankViewModel.swift +++ b/FullStackCodingBot/FullStackCodingBot/ViewModel/RankViewModel.swift @@ -6,7 +6,7 @@ final class RankViewModel: CommonViewModel { let cancelAction: CocoaAction - init(sceneCoordinator: SceneCoordinatorType, storage: PersistenceStorageType, database: DatabaseManagerType, cancelAction: CocoaAction? = nil) { + init(sceneCoordinator: SceneCoordinatorType, storage: PersistenceStorageType, database: FirebaseManagerType, cancelAction: CocoaAction? = nil) { self.cancelAction = CocoaAction { if let action = cancelAction { diff --git a/FullStackCodingBot/FullStackCodingBot/ViewModel/ShopViewModel.swift b/FullStackCodingBot/FullStackCodingBot/ViewModel/ShopViewModel.swift index a0e93b3..98c8885 100644 --- a/FullStackCodingBot/FullStackCodingBot/ViewModel/ShopViewModel.swift +++ b/FullStackCodingBot/FullStackCodingBot/ViewModel/ShopViewModel.swift @@ -24,7 +24,7 @@ final class ShopViewModel: AdViewModel { init(sceneCoordinator: SceneCoordinatorType, storage: PersistenceStorageType, adStorage: AdStorageType, - database: DatabaseManagerType, + database: FirebaseManagerType, cancelAction: CocoaAction? = nil, soundEffectType: MainSoundEffect = .reward) { self.cancelAction = CocoaAction { diff --git a/FullStackCodingBot/FullStackCodingBot/ViewModel/StoryViewModel.swift b/FullStackCodingBot/FullStackCodingBot/ViewModel/StoryViewModel.swift index ab0fc2a..4dcd166 100644 --- a/FullStackCodingBot/FullStackCodingBot/ViewModel/StoryViewModel.swift +++ b/FullStackCodingBot/FullStackCodingBot/ViewModel/StoryViewModel.swift @@ -12,7 +12,7 @@ final class StoryViewModel: AdViewModel { init(sceneCoordinator: SceneCoordinatorType, storage: PersistenceStorageType, adStorage: AdStorageType, - database: DatabaseManagerType, + database: FirebaseManagerType, settings: SettingInformation, storyManger: StoryManager = StoryManager(), isFirstTimePlay: Bool = true) { From bb411c98e912745050fa9bf15175d05e3fd04254 Mon Sep 17 00:00:00 2001 From: Song Lee Date: Wed, 15 Sep 2021 13:11:43 +0900 Subject: [PATCH 03/17] =?UTF-8?q?refactor:=20[#191]=20=EB=A9=94=EC=86=8C?= =?UTF-8?q?=EB=93=9C=20=EC=9D=B4=EB=A6=84=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../FullStackCodingBot/AppCycle/AppDelegate.swift | 2 +- .../Service/Storage/BackUpManager/BackUpCenter.swift | 2 +- .../Storage/BackUpManager/FirebaseManager.swift | 4 ++-- .../Storage/BackUpManager/FirebaseManagerType.swift | 4 ++-- .../FullStackCodingBot/Service/Storage/Storage.swift | 2 +- .../FullStackCodingBot/ViewModel/MainViewModel.swift | 2 +- FullStackCodingBot/Podfile.lock | 12 ++---------- 7 files changed, 10 insertions(+), 18 deletions(-) diff --git a/FullStackCodingBot/FullStackCodingBot/AppCycle/AppDelegate.swift b/FullStackCodingBot/FullStackCodingBot/AppCycle/AppDelegate.swift index 016762a..e4d155c 100644 --- a/FullStackCodingBot/FullStackCodingBot/AppCycle/AppDelegate.swift +++ b/FullStackCodingBot/FullStackCodingBot/AppCycle/AppDelegate.swift @@ -23,7 +23,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate { let database = FirebaseManager(Database.database().reference()) let networkDTO = NetworkDTO(units: storage.itemList(), money: storage.myMoney(), score: storage.myHighScore(), ads: adStorage.currentInformation(), date: Date()) if storage.itemList().isEmpty { return } - database.updateDatabase(networkDTO) + database.save(networkDTO) } } diff --git a/FullStackCodingBot/FullStackCodingBot/Service/Storage/BackUpManager/BackUpCenter.swift b/FullStackCodingBot/FullStackCodingBot/Service/Storage/BackUpManager/BackUpCenter.swift index c586bf8..eff7e5e 100644 --- a/FullStackCodingBot/FullStackCodingBot/Service/Storage/BackUpManager/BackUpCenter.swift +++ b/FullStackCodingBot/FullStackCodingBot/Service/Storage/BackUpManager/BackUpCenter.swift @@ -25,7 +25,7 @@ final class BackUpCenter: BackUpCenterType { return Disposables.create() } - firebaseManager.getFirebaseData(uuid) + firebaseManager.load(uuid) .subscribe { onlineData in let onlineUpdate = onlineData.date let localUpdate = localData.date diff --git a/FullStackCodingBot/FullStackCodingBot/Service/Storage/BackUpManager/FirebaseManager.swift b/FullStackCodingBot/FullStackCodingBot/Service/Storage/BackUpManager/FirebaseManager.swift index 0aab4f2..08d23b0 100644 --- a/FullStackCodingBot/FullStackCodingBot/Service/Storage/BackUpManager/FirebaseManager.swift +++ b/FullStackCodingBot/FullStackCodingBot/Service/Storage/BackUpManager/FirebaseManager.swift @@ -13,7 +13,7 @@ final class FirebaseManager: FirebaseManagerType { self.ref = ref } - func updateDatabase(_ info: NetworkDTO) { + func save(_ info: NetworkDTO) { guard uid != "" else { return } let unitData = try? DataFormatManager.transformToString(info.units) @@ -25,7 +25,7 @@ final class FirebaseManager: FirebaseManagerType { } @discardableResult - func getFirebaseData(_ uuid: String) -> Observable { + func load(_ uuid: String) -> Observable { Observable.create { [unowned self] observer in self.ref.child("users").child(uuid).getData { error, snapshot in if let error = error { diff --git a/FullStackCodingBot/FullStackCodingBot/Service/Storage/BackUpManager/FirebaseManagerType.swift b/FullStackCodingBot/FullStackCodingBot/Service/Storage/BackUpManager/FirebaseManagerType.swift index 6a3a892..4b78ea5 100644 --- a/FullStackCodingBot/FullStackCodingBot/Service/Storage/BackUpManager/FirebaseManagerType.swift +++ b/FullStackCodingBot/FullStackCodingBot/Service/Storage/BackUpManager/FirebaseManagerType.swift @@ -4,7 +4,7 @@ import RxSwift protocol FirebaseManagerType { @discardableResult - func getFirebaseData(_ uuid: String) -> Observable + func load(_ uuid: String) -> Observable - func updateDatabase(_ info: NetworkDTO) + func save(_ info: NetworkDTO) } diff --git a/FullStackCodingBot/FullStackCodingBot/Service/Storage/Storage.swift b/FullStackCodingBot/FullStackCodingBot/Service/Storage/Storage.swift index f77c86b..44030be 100644 --- a/FullStackCodingBot/FullStackCodingBot/Service/Storage/Storage.swift +++ b/FullStackCodingBot/FullStackCodingBot/Service/Storage/Storage.swift @@ -13,7 +13,7 @@ final class Storage { self.backUpCenter = backUpCenter } - func fill(using uuid: String?, isFirstLaunched: Bool) -> Observable { + func initializeData(using uuid: String?, isFirstLaunched: Bool) -> Observable { Observable.create { [weak self] observer in self?.backUpCenter.load(with: uuid, isFirstLaunched) .observe(on: MainScheduler.asyncInstance) diff --git a/FullStackCodingBot/FullStackCodingBot/ViewModel/MainViewModel.swift b/FullStackCodingBot/FullStackCodingBot/ViewModel/MainViewModel.swift index 68655db..9f144c0 100644 --- a/FullStackCodingBot/FullStackCodingBot/ViewModel/MainViewModel.swift +++ b/FullStackCodingBot/FullStackCodingBot/ViewModel/MainViewModel.swift @@ -150,7 +150,7 @@ extension MainViewModel { private func load(with uuid: String?) { let isFirstLaunched = !userDefaults.bool(forKey: IdentifierUD.hasLaunchedOnce) - newStorage.fill(using: uuid, isFirstLaunched: isFirstLaunched) + newStorage.initializeData(using: uuid, isFirstLaunched: isFirstLaunched) .observe(on: MainScheduler.asyncInstance) .subscribe(onNext: { [unowned self] isLoaded in self.firebaseDidLoad.accept(isLoaded) diff --git a/FullStackCodingBot/Podfile.lock b/FullStackCodingBot/Podfile.lock index e88a09f..c26b996 100644 --- a/FullStackCodingBot/Podfile.lock +++ b/FullStackCodingBot/Podfile.lock @@ -2,7 +2,6 @@ PODS: - Action (5.0.0): - RxCocoa (~> 6.0) - RxSwift (~> 6.0) - - Alamofire (5.4.3) - Firebase/Auth (8.6.1): - Firebase/CoreOnly - FirebaseAuth (~> 8.6.0) @@ -54,7 +53,6 @@ PODS: - GoogleUtilities/Environment (~> 7.4) - GoogleUtilities/UserDefaults (~> 7.4) - PromisesObjC (< 3.0, >= 1.2) - - GhostTypewriter (2.1.0) - Google-Mobile-Ads-SDK (8.9.0): - GoogleAppMeasurement (< 9.0, >= 7.0) - GoogleUserMessagingPlatform (>= 1.1) @@ -115,11 +113,9 @@ PODS: DEPENDENCIES: - Action - - Alamofire - Firebase/Auth - Firebase/Core - Firebase/Database - - GhostTypewriter - Google-Mobile-Ads-SDK - "NSObject+Rx" - RxCocoa @@ -129,7 +125,6 @@ DEPENDENCIES: SPEC REPOS: trunk: - Action - - Alamofire - Firebase - FirebaseAnalytics - FirebaseAuth @@ -137,7 +132,6 @@ SPEC REPOS: - FirebaseCoreDiagnostics - FirebaseDatabase - FirebaseInstallations - - GhostTypewriter - Google-Mobile-Ads-SDK - GoogleAppMeasurement - GoogleDataTransport @@ -155,7 +149,6 @@ SPEC REPOS: SPEC CHECKSUMS: Action: 47f1825511907b4fcd79dd7a7db9526c20f78018 - Alamofire: e447a2774a40c996748296fa2c55112fdbbc42f9 Firebase: e84d95f6d3a91f634abc384f0751c434cb3aecfa FirebaseAnalytics: 8f32ae54ad42754f503354782575c4ddfc1425c3 FirebaseAuth: 223adeeb2262b417532e89bf06a960e3a0a1e9e4 @@ -163,7 +156,6 @@ SPEC CHECKSUMS: FirebaseCoreDiagnostics: 3721920bde3a9a6d5aa093c1d25e9d3e47f694af FirebaseDatabase: 917fbeed577a68eb1ba0eb48c52a3aa10ac13f92 FirebaseInstallations: 0ede6ffcd215b8f93c19d9b06c1c54e2d4107e98 - GhostTypewriter: 62540772d227fbfe633bfa728d08fe8af5b4d805 Google-Mobile-Ads-SDK: 8494046b4d339275a381f6bcfafbff7adb2f515f GoogleAppMeasurement: 2c0c6e2a7ab3fe730ade6379f732bdefb46f50b0 GoogleDataTransport: 85fd18ff3019bb85d3f2c551d04c481dedf71fc9 @@ -179,6 +171,6 @@ SPEC CHECKSUMS: RxSwift: d356ab7bee873611322f134c5f9ef379fa183d8f SwiftLint: 99f82d07b837b942dd563c668de129a03fc3fb52 -PODFILE CHECKSUM: 53f52a813cf20cabe3f6bcb0c64867ca42b773ea +PODFILE CHECKSUM: bdce34f2ae6ceca45889e75fa0818ccb2cad524f -COCOAPODS: 1.10.0 +COCOAPODS: 1.10.2 From 927dc5b645f25e4ddcaa1ba26d7ca53049757c1c Mon Sep 17 00:00:00 2001 From: Song Lee Date: Wed, 15 Sep 2021 13:12:23 +0900 Subject: [PATCH 04/17] =?UTF-8?q?refactor:=20[#191]=20=EC=93=B0=EC=A7=80?= =?UTF-8?q?=20=EC=95=8A=EB=8A=94=20=ED=94=84=EB=A1=9C=ED=8D=BC=ED=8B=B0=20?= =?UTF-8?q?=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Service/Storage/BackUpManager/FirebaseManager.swift | 1 - 1 file changed, 1 deletion(-) diff --git a/FullStackCodingBot/FullStackCodingBot/Service/Storage/BackUpManager/FirebaseManager.swift b/FullStackCodingBot/FullStackCodingBot/Service/Storage/BackUpManager/FirebaseManager.swift index 08d23b0..76d7a45 100644 --- a/FullStackCodingBot/FullStackCodingBot/Service/Storage/BackUpManager/FirebaseManager.swift +++ b/FullStackCodingBot/FullStackCodingBot/Service/Storage/BackUpManager/FirebaseManager.swift @@ -7,7 +7,6 @@ final class FirebaseManager: FirebaseManagerType { private var ref: DatabaseReference private let uid = Auth.auth().currentUser?.uid ?? "" private let disposedBag = DisposeBag() - let data = [Unit]() init(_ ref: DatabaseReference = Database.database().reference()) { self.ref = ref From 1b98ac1b08a4fb769089162be103887f9a503735 Mon Sep 17 00:00:00 2001 From: Song Lee Date: Wed, 15 Sep 2021 13:17:24 +0900 Subject: [PATCH 05/17] =?UTF-8?q?refactor;=20[#191]=20DataFormatManager=20?= =?UTF-8?q?=EB=94=94=EB=A0=89=ED=86=A0=EB=A6=AC=20=EC=9D=B4=EB=8F=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - BackUp과 관련한 기능으로 판단 --- FullStackCodingBot/FullStackCodingBot.xcodeproj/project.pbxproj | 2 +- .../BackUpManager}/DataFormatManager/DataFormatManager.swift | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename FullStackCodingBot/FullStackCodingBot/Service/{ => Storage/BackUpManager}/DataFormatManager/DataFormatManager.swift (100%) diff --git a/FullStackCodingBot/FullStackCodingBot.xcodeproj/project.pbxproj b/FullStackCodingBot/FullStackCodingBot.xcodeproj/project.pbxproj index 0a38903..bf3ad30 100644 --- a/FullStackCodingBot/FullStackCodingBot.xcodeproj/project.pbxproj +++ b/FullStackCodingBot/FullStackCodingBot.xcodeproj/project.pbxproj @@ -347,7 +347,6 @@ children = ( E4336F6426F08A8D0049A5D8 /* Storage */, 717EAD3B26A656E200E0CDB7 /* GameLogic */, - 71BC752C26A940870021BA1A /* DataFormatManager */, 718F224726C377AA00B2648C /* ErrorManager */, ); path = Service; @@ -656,6 +655,7 @@ E4336F6226F083C30049A5D8 /* CoreDataManagerType.swift */, 71A5517F26A91C280083A4B0 /* FirebaseManager.swift */, 71A5518126A9277C0083A4B0 /* FirebaseManagerType.swift */, + 71BC752C26A940870021BA1A /* DataFormatManager */, ); path = BackUpManager; sourceTree = ""; diff --git a/FullStackCodingBot/FullStackCodingBot/Service/DataFormatManager/DataFormatManager.swift b/FullStackCodingBot/FullStackCodingBot/Service/Storage/BackUpManager/DataFormatManager/DataFormatManager.swift similarity index 100% rename from FullStackCodingBot/FullStackCodingBot/Service/DataFormatManager/DataFormatManager.swift rename to FullStackCodingBot/FullStackCodingBot/Service/Storage/BackUpManager/DataFormatManager/DataFormatManager.swift From 06fea17f70cc91f765eb89734fb628c2029cb8ed Mon Sep 17 00:00:00 2001 From: Song Lee Date: Wed, 15 Sep 2021 14:05:04 +0900 Subject: [PATCH 06/17] =?UTF-8?q?refactor:=20[#191]=20CoreData=20=E1=84=80?= =?UTF-8?q?=E1=85=AA=E1=86=AB=E1=84=85=E1=85=A7=E1=86=AB=20=E1=84=80?= =?UTF-8?q?=E1=85=B5=E1=84=82=E1=85=B3=E1=86=BC=E1=84=86=E1=85=A1=E1=86=AB?= =?UTF-8?q?=20=E1=84=89=E1=85=AE=E1=84=92=E1=85=A2=E1=86=BC=E1=84=92?= =?UTF-8?q?=E1=85=A1=E1=84=82=E1=85=B3=E1=86=AB=20=E1=84=80=E1=85=A2?= =?UTF-8?q?=E1=86=A8=E1=84=8E=E1=85=A6=20=E1=84=89=E1=85=B5=E1=86=AB?= =?UTF-8?q?=E1=84=89=E1=85=A5=E1=86=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../project.pbxproj | 4 + .../BackUpManager/CoreDataManager.swift | 199 ++++++++++++++++++ 2 files changed, 203 insertions(+) create mode 100644 FullStackCodingBot/FullStackCodingBot/Service/Storage/BackUpManager/CoreDataManager.swift diff --git a/FullStackCodingBot/FullStackCodingBot.xcodeproj/project.pbxproj b/FullStackCodingBot/FullStackCodingBot.xcodeproj/project.pbxproj index bf3ad30..7f413f2 100644 --- a/FullStackCodingBot/FullStackCodingBot.xcodeproj/project.pbxproj +++ b/FullStackCodingBot/FullStackCodingBot.xcodeproj/project.pbxproj @@ -87,6 +87,7 @@ E4336F5F26F083840049A5D8 /* BackUpCenterType.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4336F5E26F083840049A5D8 /* BackUpCenterType.swift */; }; E4336F6126F083A20049A5D8 /* BackUpCenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4336F6026F083A20049A5D8 /* BackUpCenter.swift */; }; E4336F6326F083C30049A5D8 /* CoreDataManagerType.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4336F6226F083C30049A5D8 /* CoreDataManagerType.swift */; }; + E4336F6826F1AB8B0049A5D8 /* CoreDataManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4336F6726F1AB8B0049A5D8 /* CoreDataManager.swift */; }; E43B64A226ABD81C001D9896 /* GameBackgroundView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E43B64A126ABD81C001D9896 /* GameBackgroundView.swift */; }; E43B64A426AC2384001D9896 /* TimeBarView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E43B64A326AC2384001D9896 /* TimeBarView.swift */; }; E45B0AB82692929F006FDE3D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = E45B0AB72692929F006FDE3D /* Assets.xcassets */; }; @@ -241,6 +242,7 @@ E4336F5E26F083840049A5D8 /* BackUpCenterType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BackUpCenterType.swift; sourceTree = ""; }; E4336F6026F083A20049A5D8 /* BackUpCenter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BackUpCenter.swift; sourceTree = ""; }; E4336F6226F083C30049A5D8 /* CoreDataManagerType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CoreDataManagerType.swift; sourceTree = ""; }; + E4336F6726F1AB8B0049A5D8 /* CoreDataManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CoreDataManager.swift; sourceTree = ""; }; E43B64A126ABD81C001D9896 /* GameBackgroundView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GameBackgroundView.swift; sourceTree = ""; }; E43B64A326AC2384001D9896 /* TimeBarView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimeBarView.swift; sourceTree = ""; }; E45B0AAB2692929D006FDE3D /* Full Stack.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Full Stack.app"; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -652,6 +654,7 @@ children = ( E4336F6026F083A20049A5D8 /* BackUpCenter.swift */, E4336F5E26F083840049A5D8 /* BackUpCenterType.swift */, + E4336F6726F1AB8B0049A5D8 /* CoreDataManager.swift */, E4336F6226F083C30049A5D8 /* CoreDataManagerType.swift */, 71A5517F26A91C280083A4B0 /* FirebaseManager.swift */, 71A5518126A9277C0083A4B0 /* FirebaseManagerType.swift */, @@ -1080,6 +1083,7 @@ E41C85DD269C50F0008F2E91 /* PauseViewModel.swift in Sources */, E41C85DF269C5149008F2E91 /* PauseButtonController.swift in Sources */, E418F36F26DC8D4800F35AFB /* UnitInfo - keyColor.swift in Sources */, + E4336F6826F1AB8B0049A5D8 /* CoreDataManager.swift in Sources */, E4779C6726983F5700B92D24 /* GameOverViewController.swift in Sources */, 71DF65532692FBE500557693 /* SceneCoordinator.swift in Sources */, E4DF613B26A845670061F6E9 /* AdStorageType.swift in Sources */, diff --git a/FullStackCodingBot/FullStackCodingBot/Service/Storage/BackUpManager/CoreDataManager.swift b/FullStackCodingBot/FullStackCodingBot/Service/Storage/BackUpManager/CoreDataManager.swift new file mode 100644 index 0000000..c052981 --- /dev/null +++ b/FullStackCodingBot/FullStackCodingBot/Service/Storage/BackUpManager/CoreDataManager.swift @@ -0,0 +1,199 @@ +import Foundation +import CoreData +import RxSwift + +final class CoreDataManager { + + private lazy var persistentContainer: NSPersistentContainer = { + let container = NSPersistentContainer(name: "CoreDataStorage") + container.loadPersistentStores { _, error in + if let error = error { + fatalError() + } + } + return container + }() + + private var context: NSManagedObjectContext { + return persistentContainer.viewContext + } + + func setupInitialData() -> Completable { + let subject = PublishSubject() + let initialUnits = Unit.initialValues() + + do { + try appendUnitInfos(initialUnits) + try appendMoneyInfo(0) + try appendScoreInfo(0) + } catch { + subject.onError(CoreDataError.cannotFetchData) + } + subject.onCompleted() + return subject.ignoreElements().asCompletable() + } + + func load() -> Observable { + Observable.create { [weak self] observer in + guard let fetchedUnitInfo = try? self?.fetchUnit(), + let fetchedMoneyInfo = try? self?.fetchMoneyInfo().first, + let fetchedScoreInfo = try? self?.fetchScoreInfo().first else { + observer.onError(CoreDataError.cannotFetchData) + return Disposables.create() + } + + let units = fetchedUnitInfo.map { DataFormatManager.transformToUnit($0) } + let money = Int(fetchedMoneyInfo.myMoney) + let score = Int(fetchedScoreInfo.myScore) + let date = fetchedMoneyInfo.lastUpdated ?? .init(timeIntervalSince1970: 0) + let localData = NetworkDTO.init(units: units, + money: money, + score: score, + ads: .empty(), + date: date) + observer.onNext(localData) + observer.onCompleted() + return Disposables.create() + } + } + + func lastUpdated() -> Date { + let farPastDate = Date.init(timeIntervalSince1970: 0) + guard let fetchedInfo = try? fetchMoneyInfo(), + let currentMoneyInfo = fetchedInfo.first else { + return farPastDate + } + let lastUpdated = currentMoneyInfo.lastUpdated ?? farPastDate + return lastUpdated + } +} + +// MARK: new +extension CoreDataManager { + private func appendUnitInfos(_ units: [Unit]) throws { + let fetchedUnit = try? fetchUnit().first + guard fetchedUnit == nil else { return } + + try units.forEach { unit in + if let entity = NSEntityDescription.entity(forEntityName: "ItemInformation", in: context) { + let info = NSManagedObject(entity: entity, insertInto: context) + info.setValue(unit.uuid, forKey: "uuid") + info.setValue(unit.image, forKey: "image") + info.setValue(unit.level, forKey: "level") + + do { + try context.save() + } catch { + throw CoreDataError.cannotSaveData + } + } + } + } + + private func appendMoneyInfo(_ money: Int) throws { + let fetchedMoney = try? fetchMoneyInfo().first + guard fetchedMoney == nil else { return } + + if let entity = NSEntityDescription.entity(forEntityName: "MoneyInformation", in: context) { + let info = NSManagedObject(entity: entity, insertInto: context) + info.setValue(money, forKey: "myMoney") + info.setValue(Date.init(timeIntervalSince1970: 0), forKey: "lastUpdated") + + do { + try context.save() + } catch { + throw CoreDataError.cannotSaveData + } + } + } + + private func appendScoreInfo(_ score: Int) throws { + let fetchedScore = try? fetchScoreInfo().first + guard fetchedScore == nil else { return } + + if let entity = NSEntityDescription.entity(forEntityName: "ScoreInformation", in: context) { + let info = NSManagedObject(entity: entity, insertInto: context) + info.setValue(score, forKey: "myScore") + + do { + try context.save() + } catch { + throw CoreDataError.cannotSaveData + } + } + } +} + +// MARK: load +extension CoreDataManager { + private func fetchUnit() throws -> [ItemInformation] { + do { + guard let fetchResult = try context.fetch(ItemInformation.fetchRequest()) as? [ItemInformation] else { return [] } + return fetchResult + } catch { + throw CoreDataError.cannotFetchData + } + } + + private func fetchMoneyInfo() throws -> [MoneyInformation] { + do { + guard let fetchResult = try context.fetch(MoneyInformation.fetchRequest()) as? [MoneyInformation] else { + return [MoneyInformation(context: context)] + } + return fetchResult + } catch { + throw CoreDataError.cannotFetchData + } + } + + private func fetchScoreInfo() throws -> [ScoreInformation] { + do { + guard let fetchResult = try context.fetch(ScoreInformation.fetchRequest()) as? [ScoreInformation] else { + return [ScoreInformation(context: context)] + } + return fetchResult + } catch { + throw CoreDataError.cannotFetchData + } + } +} + +// MARK: save +extension CoreDataManager { + private func updateUnit(to unit: Unit) throws { + guard let fetchedUnit = try? fetchUnit() else { return } + + for info in fetchedUnit where info.uuid == unit.uuid { + info.setValue(unit.uuid, forKey: "uuid") + info.setValue(unit.image, forKey: "image") + info.setValue(unit.level, forKey: "level") + } + + do { + try context.save() + } catch { + throw CoreDataError.cannotSaveData + } + } + + private func updateMoney(money: Int) throws { + do { + let previousInfo = try fetchMoneyInfo().first ?? MoneyInformation(context: context) + previousInfo.setValue(money, forKey: "myMoney") + previousInfo.setValue(Date(), forKey: "lastUpdated") + try context.save() + } catch { + throw CoreDataError.cannotSaveData + } + } + + private func updateScore(score: Int) throws { + do { + let previousInfo = try fetchScoreInfo().first ?? ScoreInformation(context: context) + previousInfo.setValue(score, forKey: "myScore") + try context.save() + } catch { + throw CoreDataError.cannotSaveData + } + } +} From d8fe0930d61d5267cb454c26c3c40bca7c7d59bf Mon Sep 17 00:00:00 2001 From: Song Lee Date: Wed, 15 Sep 2021 14:23:37 +0900 Subject: [PATCH 07/17] =?UTF-8?q?refactor:=20[#191]=20Game=20=E1=84=83?= =?UTF-8?q?=E1=85=A6=E1=84=8B=E1=85=B5=E1=84=90=E1=85=A5=20=E1=84=80?= =?UTF-8?q?=E1=85=AA=E1=86=AB=E1=84=85=E1=85=B5=20=E1=84=80=E1=85=A2?= =?UTF-8?q?=E1=86=A8=E1=84=8E=E1=85=A6=20=E1=84=89=E1=85=B5=E1=86=AB?= =?UTF-8?q?=E1=84=89=E1=85=A5=E1=86=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 기존 PersistenceStorage의 책임을 옮겨 옴 --- .../project.pbxproj | 4 + .../Storage/RealDataStorage/GameStorage.swift | 98 +++++++++++++++++++ .../RealDataStorage/GameStorageType.swift | 37 ++++--- 3 files changed, 128 insertions(+), 11 deletions(-) create mode 100644 FullStackCodingBot/FullStackCodingBot/Service/Storage/RealDataStorage/GameStorage.swift diff --git a/FullStackCodingBot/FullStackCodingBot.xcodeproj/project.pbxproj b/FullStackCodingBot/FullStackCodingBot.xcodeproj/project.pbxproj index 7f413f2..79bbd88 100644 --- a/FullStackCodingBot/FullStackCodingBot.xcodeproj/project.pbxproj +++ b/FullStackCodingBot/FullStackCodingBot.xcodeproj/project.pbxproj @@ -88,6 +88,7 @@ E4336F6126F083A20049A5D8 /* BackUpCenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4336F6026F083A20049A5D8 /* BackUpCenter.swift */; }; E4336F6326F083C30049A5D8 /* CoreDataManagerType.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4336F6226F083C30049A5D8 /* CoreDataManagerType.swift */; }; E4336F6826F1AB8B0049A5D8 /* CoreDataManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4336F6726F1AB8B0049A5D8 /* CoreDataManager.swift */; }; + E4336F6A26F1B7500049A5D8 /* GameStorage.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4336F6926F1B7500049A5D8 /* GameStorage.swift */; }; E43B64A226ABD81C001D9896 /* GameBackgroundView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E43B64A126ABD81C001D9896 /* GameBackgroundView.swift */; }; E43B64A426AC2384001D9896 /* TimeBarView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E43B64A326AC2384001D9896 /* TimeBarView.swift */; }; E45B0AB82692929F006FDE3D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = E45B0AB72692929F006FDE3D /* Assets.xcassets */; }; @@ -243,6 +244,7 @@ E4336F6026F083A20049A5D8 /* BackUpCenter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BackUpCenter.swift; sourceTree = ""; }; E4336F6226F083C30049A5D8 /* CoreDataManagerType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CoreDataManagerType.swift; sourceTree = ""; }; E4336F6726F1AB8B0049A5D8 /* CoreDataManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CoreDataManager.swift; sourceTree = ""; }; + E4336F6926F1B7500049A5D8 /* GameStorage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GameStorage.swift; sourceTree = ""; }; E43B64A126ABD81C001D9896 /* GameBackgroundView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GameBackgroundView.swift; sourceTree = ""; }; E43B64A326AC2384001D9896 /* TimeBarView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimeBarView.swift; sourceTree = ""; }; E45B0AAB2692929D006FDE3D /* Full Stack.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Full Stack.app"; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -642,6 +644,7 @@ children = ( E4DF613C26A845DA0061F6E9 /* AdStorage.swift */, E4DF613A26A845670061F6E9 /* AdStorageType.swift */, + E4336F6926F1B7500049A5D8 /* GameStorage.swift */, E4336F5C26F083650049A5D8 /* GameStorageType.swift */, 71E2B37526AE5E7F00AE496D /* PersistenceStorage.swift */, 71E2B37726AE602200AE496D /* PersistenceStorageType.swift */, @@ -1128,6 +1131,7 @@ 71003AD626CFAB22001D5210 /* IdentifierManager.swift in Sources */, E4150E9F26BE44AC0041DD32 /* PersonStoryView.swift in Sources */, E4BF712C26B3E6E300E8645F /* UnitInformation.swift in Sources */, + E4336F6A26F1B7500049A5D8 /* GameStorage.swift in Sources */, E4150E9926BA37C10041DD32 /* FadeInTextView.swift in Sources */, 7166B24026C25B0400E098BE /* Manual.swift in Sources */, E4779C652697E92F00B92D24 /* TimeProgressView.swift in Sources */, diff --git a/FullStackCodingBot/FullStackCodingBot/Service/Storage/RealDataStorage/GameStorage.swift b/FullStackCodingBot/FullStackCodingBot/Service/Storage/RealDataStorage/GameStorage.swift new file mode 100644 index 0000000..54a75d9 --- /dev/null +++ b/FullStackCodingBot/FullStackCodingBot/Service/Storage/RealDataStorage/GameStorage.swift @@ -0,0 +1,98 @@ +import Foundation +import RxSwift + +final class GameStorage: GameStorageType { + + private var unitStore: [Unit] = [] + private lazy var unitList = BehaviorSubject<[Unit]>(value: unitStore) + private var moneyStore = 0 + private lazy var moneyStatus = BehaviorSubject(value: moneyStore) + private var highScore = 0 + + @discardableResult + func myHighScore() -> Int { + return highScore + } + + @discardableResult + func myMoney() -> Int { + return moneyStore + } + + @discardableResult + func itemList() -> [Unit] { + return unitStore + } + + func update(with data: NetworkDTO) { + unitStore = data.units + highScore = data.score + moneyStore = data.money + } + + @discardableResult + func update(units: [Unit]) -> Observable<[Unit]> { + unitStore = filtered(units) + unitList.onNext(unitStore) + return Observable.just(units) + } + + private func filtered(_ units: [Unit]) -> [Unit] { + if units.count == UnitInfo.allCases.count { + return units + } + + // 1.0.2 #180 중복 유닛 생성 버그 -> 업그레이드된 유닛이 있을 경우 레벨이 높은 유닛으로 storage 생성 + var finalUnits = Unit.initialValues() + + units.forEach { unit in + let currentId = unit.uuid + let currentLevel = unit.level + let currentHighestLevel = finalUnits[currentId].level + if currentLevel >= currentHighestLevel { + finalUnits[currentId] = unit + } + } + return finalUnits + } + + @discardableResult + func listUnit() -> Observable<[Unit]> { + return unitList + } + + @discardableResult + func raiseLevel(of unit: Unit, using money: Int) -> Unit { + let newUnit = Unit(original: unit, level: unit.level+1) + if let index = unitStore.firstIndex(where: { $0 == unit}) { + unitStore.remove(at: index) + unitStore.insert(newUnit, at: index) + moneyStore -= money + } + unitList.onNext(unitStore) + moneyStatus.onNext(moneyStore) + return newUnit + } + + @discardableResult + func availableMoney() -> Observable { + return moneyStatus + } + + @discardableResult + func raiseMoney(by money: Int) -> Observable { + moneyStore += money + moneyStatus.onNext(moneyStore) + return Observable.just(money) + } + + @discardableResult + func updateHighScore(new score: Int) -> Bool { + if score > highScore { + highScore = score + return true + } else { + return false + } + } +} diff --git a/FullStackCodingBot/FullStackCodingBot/Service/Storage/RealDataStorage/GameStorageType.swift b/FullStackCodingBot/FullStackCodingBot/Service/Storage/RealDataStorage/GameStorageType.swift index 41372fe..6439ea4 100644 --- a/FullStackCodingBot/FullStackCodingBot/Service/Storage/RealDataStorage/GameStorageType.swift +++ b/FullStackCodingBot/FullStackCodingBot/Service/Storage/RealDataStorage/GameStorageType.swift @@ -1,16 +1,31 @@ import Foundation +import RxSwift protocol GameStorageType { + + @discardableResult + func myHighScore() -> Int + + @discardableResult + func myMoney() -> Int + + @discardableResult + func itemList() -> [Unit] + func update(with data: NetworkDTO) -} - -class FakeGameStorage: GameStorageType { - func update(with data: NetworkDTO) { - /* - ViewModel에서 다음과 같은 코드로 업데이트를 했었다 - storage.update(units: info.units) - storage.raiseMoney(by: info.money) - storage.updateHighScore(new: info.score) - */ - } + + @discardableResult + func listUnit() -> Observable<[Unit]> + + @discardableResult + func raiseLevel(of unit: Unit, using money: Int) -> Unit + + @discardableResult + func availableMoney() -> Observable + + @discardableResult + func raiseMoney(by money: Int) -> Observable + + @discardableResult + func updateHighScore(new score: Int) -> Bool } From 5c5e9f34897a1993b35e6f57ce8902ed317eb146 Mon Sep 17 00:00:00 2001 From: Song Lee Date: Wed, 15 Sep 2021 14:49:02 +0900 Subject: [PATCH 08/17] =?UTF-8?q?refactor:=20[#191]=20PersistenceStorage?= =?UTF-8?q?=20=EC=82=AD=EC=A0=9C=EC=97=90=20=EB=94=B0=EB=A5=B8=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - ViewModel 이니셜라이저 변경 - 새 객체들의 인터페이스 정의 - 임시 메소드 생성 --- .../project.pbxproj | 16 +- .../AppCycle/AppDelegate.swift | 19 +- .../Storage/BackUpManager/BackUpCenter.swift | 4 +- .../BackUpManager/CoreDataManager.swift | 40 ++- .../BackUpManager/CoreDataManagerType.swift | 17 +- .../RealDataStorage/PersistenceStorage.swift | 289 ------------------ .../PersistenceStorageType.swift | 42 --- .../Service/Storage/Storage.swift | 50 +++ .../Service/Storage/StorageType.swift | 28 ++ .../ViewModel/AdViewModel.swift | 9 +- .../ViewModel/CommonViewModel.swift | 6 +- .../ViewModel/GameOverViewModel.swift | 7 +- .../ViewModel/GameViewModel.swift | 9 +- .../ViewModel/HowToPlayViewModel.swift | 10 +- .../ViewModel/ItemViewModel.swift | 11 +- .../ViewModel/MainViewModel.swift | 39 +-- .../ViewModel/PauseViewModel.swift | 4 +- .../ViewModel/RankViewModel.swift | 7 +- .../ViewModel/ShopViewModel.swift | 26 +- .../ViewModel/StoryViewModel.swift | 8 +- 20 files changed, 164 insertions(+), 477 deletions(-) delete mode 100644 FullStackCodingBot/FullStackCodingBot/Service/Storage/RealDataStorage/PersistenceStorage.swift delete mode 100644 FullStackCodingBot/FullStackCodingBot/Service/Storage/RealDataStorage/PersistenceStorageType.swift create mode 100644 FullStackCodingBot/FullStackCodingBot/Service/Storage/StorageType.swift diff --git a/FullStackCodingBot/FullStackCodingBot.xcodeproj/project.pbxproj b/FullStackCodingBot/FullStackCodingBot.xcodeproj/project.pbxproj index 79bbd88..5436b2e 100644 --- a/FullStackCodingBot/FullStackCodingBot.xcodeproj/project.pbxproj +++ b/FullStackCodingBot/FullStackCodingBot.xcodeproj/project.pbxproj @@ -57,12 +57,8 @@ 71DF65512692FBCC00557693 /* SceneCoordinatorType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 71DF65502692FBCC00557693 /* SceneCoordinatorType.swift */; }; 71DF65532692FBE500557693 /* SceneCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 71DF65522692FBE500557693 /* SceneCoordinator.swift */; }; 71DF65552692FD1400557693 /* CommonViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 71DF65542692FD1400557693 /* CommonViewModel.swift */; }; - 71E2B37626AE5E7F00AE496D /* PersistenceStorage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 71E2B37526AE5E7F00AE496D /* PersistenceStorage.swift */; }; - 71E2B37826AE602200AE496D /* PersistenceStorageType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 71E2B37726AE602200AE496D /* PersistenceStorageType.swift */; }; 71E2FD9B26B90C5A0032A54B /* SettingSwitchController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 71E2FD9A26B90C5A0032A54B /* SettingSwitchController.swift */; }; 71E91E1726BA33190016386E /* Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 71E91E1626BA33190016386E /* Extension.swift */; }; - 71F0D3D926CD161700E45283 /* PersistenceStorageType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 71E2B37726AE602200AE496D /* PersistenceStorageType.swift */; }; - 71F0D3DA26CD161A00E45283 /* PersistenceStorage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 71E2B37526AE5E7F00AE496D /* PersistenceStorage.swift */; }; 71F0D3DB26CD16D500E45283 /* UnitInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4F4304526CA2E4400F046E9 /* UnitInfo.swift */; }; A0DEDFDADFEC4895FB093823 /* Pods_Full_Stack_Full_StackTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CFA3377E4ACD3B197620DEA8 /* Pods_Full_Stack_Full_StackTests.framework */; }; E4150E9726B8F3E00041DD32 /* TypeWriterView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4150E9626B8F3E00041DD32 /* TypeWriterView.swift */; }; @@ -89,6 +85,7 @@ E4336F6326F083C30049A5D8 /* CoreDataManagerType.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4336F6226F083C30049A5D8 /* CoreDataManagerType.swift */; }; E4336F6826F1AB8B0049A5D8 /* CoreDataManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4336F6726F1AB8B0049A5D8 /* CoreDataManager.swift */; }; E4336F6A26F1B7500049A5D8 /* GameStorage.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4336F6926F1B7500049A5D8 /* GameStorage.swift */; }; + E4336F6C26F1BC1A0049A5D8 /* StorageType.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4336F6B26F1BC1A0049A5D8 /* StorageType.swift */; }; E43B64A226ABD81C001D9896 /* GameBackgroundView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E43B64A126ABD81C001D9896 /* GameBackgroundView.swift */; }; E43B64A426AC2384001D9896 /* TimeBarView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E43B64A326AC2384001D9896 /* TimeBarView.swift */; }; E45B0AB82692929F006FDE3D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = E45B0AB72692929F006FDE3D /* Assets.xcassets */; }; @@ -214,8 +211,6 @@ 71DF65502692FBCC00557693 /* SceneCoordinatorType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneCoordinatorType.swift; sourceTree = ""; }; 71DF65522692FBE500557693 /* SceneCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneCoordinator.swift; sourceTree = ""; }; 71DF65542692FD1400557693 /* CommonViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CommonViewModel.swift; sourceTree = ""; }; - 71E2B37526AE5E7F00AE496D /* PersistenceStorage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PersistenceStorage.swift; sourceTree = ""; }; - 71E2B37726AE602200AE496D /* PersistenceStorageType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PersistenceStorageType.swift; sourceTree = ""; }; 71E2FD9A26B90C5A0032A54B /* SettingSwitchController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingSwitchController.swift; sourceTree = ""; }; 71E91E1626BA33190016386E /* Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Extension.swift; sourceTree = ""; }; A9E77F924F0C6B24A39E65B2 /* Pods_Full_Stack.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Full_Stack.framework; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -245,6 +240,7 @@ E4336F6226F083C30049A5D8 /* CoreDataManagerType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CoreDataManagerType.swift; sourceTree = ""; }; E4336F6726F1AB8B0049A5D8 /* CoreDataManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CoreDataManager.swift; sourceTree = ""; }; E4336F6926F1B7500049A5D8 /* GameStorage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GameStorage.swift; sourceTree = ""; }; + E4336F6B26F1BC1A0049A5D8 /* StorageType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StorageType.swift; sourceTree = ""; }; E43B64A126ABD81C001D9896 /* GameBackgroundView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GameBackgroundView.swift; sourceTree = ""; }; E43B64A326AC2384001D9896 /* TimeBarView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimeBarView.swift; sourceTree = ""; }; E45B0AAB2692929D006FDE3D /* Full Stack.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Full Stack.app"; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -633,6 +629,7 @@ isa = PBXGroup; children = ( E4336F5A26F0638A0049A5D8 /* Storage.swift */, + E4336F6B26F1BC1A0049A5D8 /* StorageType.swift */, E4336F6526F08AD80049A5D8 /* RealDataStorage */, E4336F6626F08AF10049A5D8 /* BackUpManager */, ); @@ -646,8 +643,6 @@ E4DF613A26A845670061F6E9 /* AdStorageType.swift */, E4336F6926F1B7500049A5D8 /* GameStorage.swift */, E4336F5C26F083650049A5D8 /* GameStorageType.swift */, - 71E2B37526AE5E7F00AE496D /* PersistenceStorage.swift */, - 71E2B37726AE602200AE496D /* PersistenceStorageType.swift */, ); path = RealDataStorage; sourceTree = ""; @@ -1025,8 +1020,6 @@ E4BF712526B3E65600E8645F /* AdStorageType.swift in Sources */, 71310C2D26AA596B00733361 /* CoreDataStorage.xcdatamodeld in Sources */, 71307AC126A5461700C3191F /* Unit.swift in Sources */, - 71F0D3DA26CD161A00E45283 /* PersistenceStorage.swift in Sources */, - 71F0D3D926CD161700E45283 /* PersistenceStorageType.swift in Sources */, E4BF712F26B3F22900E8645F /* ShopItem.swift in Sources */, 71F0D3DB26CD16D500E45283 /* UnitInfo.swift in Sources */, E4BF712D26B3E6F300E8645F /* AdsInformation.swift in Sources */, @@ -1083,6 +1076,7 @@ E4150EA426BE9A540041DD32 /* Line.swift in Sources */, E4BF710926B00EF600E8645F /* FeverTimeBarView.swift in Sources */, E4DF614326A93FFB0061F6E9 /* ShopCell.swift in Sources */, + E4336F6C26F1BC1A0049A5D8 /* StorageType.swift in Sources */, E41C85DD269C50F0008F2E91 /* PauseViewModel.swift in Sources */, E41C85DF269C5149008F2E91 /* PauseButtonController.swift in Sources */, E418F36F26DC8D4800F35AFB /* UnitInfo - keyColor.swift in Sources */, @@ -1106,7 +1100,6 @@ 718F224926C377B700B2648C /* ErrorManager.swift in Sources */, 71307A8926A529F400C3191F /* LevelUpButton.swift in Sources */, E4DF614126A92CE00061F6E9 /* ShopItem.swift in Sources */, - 71E2B37826AE602200AE496D /* PersistenceStorageType.swift in Sources */, E4F4304426C4F8F500F046E9 /* GameStoryManager.swift in Sources */, E4F4304626CA2E4500F046E9 /* UnitInfo.swift in Sources */, E4BF713B26B7D2CC00E8645F /* SingleSoundEffectStation.swift in Sources */, @@ -1144,7 +1137,6 @@ E41C85D6269C1C35008F2E91 /* GameOverButtonController.swift in Sources */, 71DF65412692F94E00557693 /* MainViewModel.swift in Sources */, E4DB63EA26CD3EF700E51540 /* LoadingView.swift in Sources */, - 71E2B37626AE5E7F00AE496D /* PersistenceStorage.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/FullStackCodingBot/FullStackCodingBot/AppCycle/AppDelegate.swift b/FullStackCodingBot/FullStackCodingBot/AppCycle/AppDelegate.swift index e4d155c..9ab3de1 100644 --- a/FullStackCodingBot/FullStackCodingBot/AppCycle/AppDelegate.swift +++ b/FullStackCodingBot/FullStackCodingBot/AppCycle/AppDelegate.swift @@ -7,8 +7,10 @@ import AVFoundation class AppDelegate: UIResponder, UIApplicationDelegate { var window: UIWindow? - private let storage = PersistenceStorage() - private let adStorage = AdStorage() + private let storage: StorageType = Storage(gameStorage: GameStorage(), + adStorage: AdStorage(), + backUpCenter: BackUpCenter(firebaseManager: FirebaseManager(), + coreDataManager: CoreDataManager())) private let userDefaults = UserDefaults.standard func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { @@ -20,10 +22,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate { } func applicationDidEnterBackground(_ application: UIApplication) { - let database = FirebaseManager(Database.database().reference()) - let networkDTO = NetworkDTO(units: storage.itemList(), money: storage.myMoney(), score: storage.myHighScore(), ads: adStorage.currentInformation(), date: Date()) - if storage.itemList().isEmpty { return } - database.save(networkDTO) + storage.save() } } @@ -45,8 +44,7 @@ private extension AppDelegate { let hasLaunchedOnce = userDefaults.bool(forKey: IdentifierUD.hasLaunchedOnce) let settings = getSettingInformation(hasLaunchedOnce) let coordinator = SceneCoordinator(window: window!) - let database = FirebaseManager(Database.database().reference()) - let scene = getFirstScene(hasLaunchedOnce, coordinator, database, settings) + let scene = getFirstScene(hasLaunchedOnce, coordinator, settings) coordinator.transition(to: scene, using: .root, with: StoryboardType.main, animated: false) } @@ -58,18 +56,17 @@ private extension AppDelegate { private func getFirstScene(_ hasLaunchedOnce: Bool, _ sceneCoordinator: SceneCoordinator, - _ database: FirebaseManager, _ settings: SettingInformation) -> Scene { switch hasLaunchedOnce { case true: - let mainViewModel = MainViewModel(sceneCoordinator: sceneCoordinator, storage: storage, adStorage: adStorage, database: database, settings: settings) + let mainViewModel = MainViewModel(sceneCoordinator: sceneCoordinator, storage: storage, settings: settings) let mainScene = Scene.main(mainViewModel) return mainScene case false: - let storyViewModel = StoryViewModel(sceneCoordinator: sceneCoordinator, storage: storage, adStorage: adStorage, database: database, settings: settings) + let storyViewModel = StoryViewModel(sceneCoordinator: sceneCoordinator, storage: storage, settings: settings) let storyScene = Scene.story(storyViewModel) return storyScene diff --git a/FullStackCodingBot/FullStackCodingBot/Service/Storage/BackUpManager/BackUpCenter.swift b/FullStackCodingBot/FullStackCodingBot/Service/Storage/BackUpManager/BackUpCenter.swift index eff7e5e..4970d03 100644 --- a/FullStackCodingBot/FullStackCodingBot/Service/Storage/BackUpManager/BackUpCenter.swift +++ b/FullStackCodingBot/FullStackCodingBot/Service/Storage/BackUpManager/BackUpCenter.swift @@ -14,10 +14,10 @@ final class BackUpCenter: BackUpCenterType { func load(with uuid: String?, _ isFirstLaunched: Bool) -> Observable { Observable.create { [unowned self] observer in if isFirstLaunched { - self.coreDataManager.create(with: NetworkDTO.empty()) + self.coreDataManager.setupInitialData() } - let localData = self.coreDataManager.read() + let localData = self.coreDataManager.load() ?? NetworkDTO.empty() guard let uuid = uuid else { observer.onNext(localData) diff --git a/FullStackCodingBot/FullStackCodingBot/Service/Storage/BackUpManager/CoreDataManager.swift b/FullStackCodingBot/FullStackCodingBot/Service/Storage/BackUpManager/CoreDataManager.swift index c052981..1ec94fa 100644 --- a/FullStackCodingBot/FullStackCodingBot/Service/Storage/BackUpManager/CoreDataManager.swift +++ b/FullStackCodingBot/FullStackCodingBot/Service/Storage/BackUpManager/CoreDataManager.swift @@ -2,7 +2,7 @@ import Foundation import CoreData import RxSwift -final class CoreDataManager { +final class CoreDataManager: CoreDataManagerType { private lazy var persistentContainer: NSPersistentContainer = { let container = NSPersistentContainer(name: "CoreDataStorage") @@ -18,6 +18,7 @@ final class CoreDataManager { return persistentContainer.viewContext } + @discardableResult func setupInitialData() -> Completable { let subject = PublishSubject() let initialUnits = Unit.initialValues() @@ -33,28 +34,23 @@ final class CoreDataManager { return subject.ignoreElements().asCompletable() } - func load() -> Observable { - Observable.create { [weak self] observer in - guard let fetchedUnitInfo = try? self?.fetchUnit(), - let fetchedMoneyInfo = try? self?.fetchMoneyInfo().first, - let fetchedScoreInfo = try? self?.fetchScoreInfo().first else { - observer.onError(CoreDataError.cannotFetchData) - return Disposables.create() - } - - let units = fetchedUnitInfo.map { DataFormatManager.transformToUnit($0) } - let money = Int(fetchedMoneyInfo.myMoney) - let score = Int(fetchedScoreInfo.myScore) - let date = fetchedMoneyInfo.lastUpdated ?? .init(timeIntervalSince1970: 0) - let localData = NetworkDTO.init(units: units, - money: money, - score: score, - ads: .empty(), - date: date) - observer.onNext(localData) - observer.onCompleted() - return Disposables.create() + func load() -> NetworkDTO? { + guard let fetchedUnitInfo = try? self.fetchUnit(), + let fetchedMoneyInfo = try? self.fetchMoneyInfo().first, + let fetchedScoreInfo = try? self.fetchScoreInfo().first else { + return nil } + + let units = fetchedUnitInfo.map { DataFormatManager.transformToUnit($0) } + let money = Int(fetchedMoneyInfo.myMoney) + let score = Int(fetchedScoreInfo.myScore) + let date = fetchedMoneyInfo.lastUpdated ?? .init(timeIntervalSince1970: 0) + let localData = NetworkDTO.init(units: units, + money: money, + score: score, + ads: .empty(), + date: date) + return localData } func lastUpdated() -> Date { diff --git a/FullStackCodingBot/FullStackCodingBot/Service/Storage/BackUpManager/CoreDataManagerType.swift b/FullStackCodingBot/FullStackCodingBot/Service/Storage/BackUpManager/CoreDataManagerType.swift index ae72450..8fca98f 100644 --- a/FullStackCodingBot/FullStackCodingBot/Service/Storage/BackUpManager/CoreDataManagerType.swift +++ b/FullStackCodingBot/FullStackCodingBot/Service/Storage/BackUpManager/CoreDataManagerType.swift @@ -1,18 +1,11 @@ import Foundation +import RxSwift protocol CoreDataManagerType { - func create(with initialData: NetworkDTO) - func read() -> NetworkDTO -} - -class FakeCoreDataManager: CoreDataManagerType { - private var data = NetworkDTO.empty() - func create(with initialData: NetworkDTO) { - self.data = initialData - } + @discardableResult + func setupInitialData() -> Completable + + func load() -> NetworkDTO? - func read() -> NetworkDTO { - return data - } } diff --git a/FullStackCodingBot/FullStackCodingBot/Service/Storage/RealDataStorage/PersistenceStorage.swift b/FullStackCodingBot/FullStackCodingBot/Service/Storage/RealDataStorage/PersistenceStorage.swift deleted file mode 100644 index 95b6e98..0000000 --- a/FullStackCodingBot/FullStackCodingBot/Service/Storage/RealDataStorage/PersistenceStorage.swift +++ /dev/null @@ -1,289 +0,0 @@ -import Foundation -import RxSwift -import CoreData -import RxCocoa - -final class PersistenceStorage: PersistenceStorageType { - - private lazy var persistentContainer: NSPersistentContainer = { - let container = NSPersistentContainer(name: "CoreDataStorage") - container.loadPersistentStores { _, error in - if let error = error { - fatalError() - } - } - return container - }() - - private var context: NSManagedObjectContext { - return persistentContainer.viewContext - } - - private var unitStore: [Unit] = [] - private lazy var unitList = BehaviorSubject<[Unit]>(value: unitStore) - private var moneyStore = 0 - private lazy var moneyStatus = BehaviorSubject(value: moneyStore) - private var highScore = 0 - - @discardableResult - func myHighScore() -> Int { - return highScore - } - - @discardableResult - func myMoney() -> Int { - return moneyStore - } - - @discardableResult - func itemList() -> [Unit] { - return unitStore - } - - @discardableResult - func update(units: [Unit]) -> Observable<[Unit]> { - unitStore = filtered(units) - unitList.onNext(unitStore) - - units.forEach { unit in - try? updateUnit(to: unit) - } - return Observable.just(units) - } - - private func filtered(_ units: [Unit]) -> [Unit] { - if units.count == UnitInfo.allCases.count { - return units - } - - // 1.0.2 #180 중복 유닛 생성 버그 -> 업그레이드된 유닛이 있을 경우 레벨이 높은 유닛으로 storage 생성 - var finalUnits = Unit.initialValues() - - units.forEach { unit in - let currentId = unit.uuid - let currentLevel = unit.level - let currentHighestLevel = finalUnits[currentId].level - if currentLevel >= currentHighestLevel { - finalUnits[currentId] = unit - } - } - return finalUnits - } - - @discardableResult - func listUnit() -> Observable<[Unit]> { - return unitList - } - - @discardableResult - func raiseLevel(of unit: Unit, using moeny: Int) -> Unit { - let newUnit = Unit(original: unit, level: unit.level+1) - if let index = unitStore.firstIndex(where: { $0 == unit}) { - unitStore.remove(at: index) - unitStore.insert(newUnit, at: index) - try? updateUnit(to: newUnit) - moneyStore -= moeny - try? updateMoney(money: moneyStore) - } - unitList.onNext(unitStore) - moneyStatus.onNext(moneyStore) - return newUnit - } - - @discardableResult - func availableMoeny() -> Observable { - return moneyStatus - } - - @discardableResult - func raiseMoney(by money: Int) -> Observable { - moneyStore += money - moneyStatus.onNext(moneyStore) - try? updateMoney(money: moneyStore) - return Observable.just(money) - } - - @discardableResult - func updateHighScore(new score: Int) -> Bool { - if score > highScore { - highScore = score - try? updateScore(score: highScore) - return true - } else { - return false - } - } - - @discardableResult - func getCoreDataInfo() -> Completable { - let subject = PublishSubject() - - guard let fetchedUnitInfo = try? fetchUnit() else { - return subject.ignoreElements().asCompletable() - } - - let units = fetchedUnitInfo.map { DataFormatManager.transformToUnit($0) } - update(units: units) - - guard let fetchedMoneyInfo = try? fetchMoneyInfo().first, - let fetchedScoreInfo = try? fetchScoreInfo().first else { - return subject.ignoreElements().asCompletable() - } - raiseMoney(by: Int(fetchedMoneyInfo.myMoney)) - updateHighScore(new: Int(fetchedScoreInfo.myScore)) - - subject.onCompleted() - return subject.ignoreElements().asCompletable() - } - - @discardableResult - func setupInitialData() -> Completable { - let subject = PublishSubject() - - let initialUnits = Unit.initialValues() - update(units: initialUnits) - - try? appendUnitInfos(initialUnits) - try? appendMoenyInfo(0) - try? appendScoreInfo(0) - - subject.onCompleted() - return subject.ignoreElements().asCompletable() - } - - func lastUpdated() -> Date { - let farPastDate = Date.init(timeIntervalSince1970: 0) - guard let fetchedInfo = try? fetchMoneyInfo(), - let currentMoneyInfo = fetchedInfo.first else { - return farPastDate - } - let lastUpdated = currentMoneyInfo.lastUpdated ?? farPastDate - return lastUpdated - } -} - -// MARK: CoreData Method -private extension PersistenceStorage { - private func fetchUnit() throws -> [ItemInformation] { - do { - guard let fetchResult = try context.fetch(ItemInformation.fetchRequest()) as? [ItemInformation] else { return [] } - return fetchResult - } catch { - throw CoreDataError.cannotFetchData - } - } - - private func fetchMoneyInfo() throws -> [MoneyInformation] { - do { - guard let fetchResult = try context.fetch(MoneyInformation.fetchRequest()) as? [MoneyInformation] else { - return [MoneyInformation(context: context)] - } - return fetchResult - } catch { - throw CoreDataError.cannotFetchData - } - } - - private func fetchScoreInfo() throws -> [ScoreInformation] { - do { - guard let fetchResult = try context.fetch(ScoreInformation.fetchRequest()) as? [ScoreInformation] else { - return [ScoreInformation(context: context)] - } - return fetchResult - } catch { - throw CoreDataError.cannotFetchData - } - } - - private func updateUnit(to unit: Unit) throws { - guard let fetchedUnit = try? fetchUnit() else { return } - - for info in fetchedUnit where info.uuid == unit.uuid { - info.setValue(unit.uuid, forKey: "uuid") - info.setValue(unit.image, forKey: "image") - info.setValue(unit.level, forKey: "level") - } - - do { - try context.save() - } catch { - throw CoreDataError.cannotSaveData - } - } - - private func updateMoney(money: Int) throws { - do { - let previousInfo = try fetchMoneyInfo().first ?? MoneyInformation(context: context) - previousInfo.setValue(money, forKey: "myMoney") - previousInfo.setValue(Date(), forKey: "lastUpdated") - try context.save() - } catch { - throw CoreDataError.cannotSaveData - } - } - - private func updateScore(score: Int) throws { - do { - let previousInfo = try fetchScoreInfo().first ?? ScoreInformation(context: context) - previousInfo.setValue(score, forKey: "myScore") - try context.save() - } catch { - throw CoreDataError.cannotSaveData - } - } - - private func appendUnitInfos(_ units: [Unit]) throws { - let fetchedUnit = try? fetchUnit().first - guard fetchedUnit == nil else { return } - - try units.forEach { unit in - if let entity = NSEntityDescription.entity(forEntityName: "ItemInformation", in: context) { - let info = NSManagedObject(entity: entity, insertInto: context) - info.setValue(unit.uuid, forKey: "uuid") - info.setValue(unit.image, forKey: "image") - info.setValue(unit.level, forKey: "level") - - do { - try context.save() - } catch { - throw CoreDataError.cannotSaveData - } - } - } - } - - private func appendMoenyInfo(_ money: Int) throws { - let fetchedMoney = try? fetchMoneyInfo().first - guard fetchedMoney == nil else { return } - - if let entity = NSEntityDescription.entity(forEntityName: "MoneyInformation", in: context) { - let info = NSManagedObject(entity: entity, insertInto: context) - info.setValue(money, forKey: "myMoney") - info.setValue(Date.init(timeIntervalSince1970: 0), forKey: "lastUpdated") - - do { - try context.save() - } catch { - throw CoreDataError.cannotSaveData - } - } - moneyStore = money - moneyStatus.onNext(moneyStore) - } - - private func appendScoreInfo(_ score: Int) throws { - let fetchedScore = try? fetchScoreInfo().first - guard fetchedScore == nil else { return } - - if let entity = NSEntityDescription.entity(forEntityName: "ScoreInformation", in: context) { - let info = NSManagedObject(entity: entity, insertInto: context) - info.setValue(score, forKey: "myScore") - - do { - try context.save() - } catch { - throw CoreDataError.cannotSaveData - } - } - } -} diff --git a/FullStackCodingBot/FullStackCodingBot/Service/Storage/RealDataStorage/PersistenceStorageType.swift b/FullStackCodingBot/FullStackCodingBot/Service/Storage/RealDataStorage/PersistenceStorageType.swift deleted file mode 100644 index c6f9926..0000000 --- a/FullStackCodingBot/FullStackCodingBot/Service/Storage/RealDataStorage/PersistenceStorageType.swift +++ /dev/null @@ -1,42 +0,0 @@ -import Foundation -import CoreData -import RxSwift -import RxCocoa - -protocol PersistenceStorageType { - - @discardableResult - func myHighScore() -> Int - - @discardableResult - func myMoney() -> Int - - @discardableResult - func itemList() -> [Unit] - - @discardableResult - func update(units: [Unit]) -> Observable<[Unit]> - - @discardableResult - func listUnit() -> Observable<[Unit]> - - @discardableResult - func raiseLevel(of unit: Unit, using moeny: Int) -> Unit - - @discardableResult - func availableMoeny() -> Observable - - @discardableResult - func raiseMoney(by money: Int) -> Observable - - @discardableResult - func updateHighScore(new score: Int) -> Bool - - @discardableResult - func getCoreDataInfo() -> Completable - - @discardableResult - func setupInitialData() -> Completable - - func lastUpdated() -> Date -} diff --git a/FullStackCodingBot/FullStackCodingBot/Service/Storage/Storage.swift b/FullStackCodingBot/FullStackCodingBot/Service/Storage/Storage.swift index 44030be..3d3335a 100644 --- a/FullStackCodingBot/FullStackCodingBot/Service/Storage/Storage.swift +++ b/FullStackCodingBot/FullStackCodingBot/Service/Storage/Storage.swift @@ -1,5 +1,6 @@ import Foundation import RxSwift +import GoogleMobileAds final class Storage { @@ -29,3 +30,52 @@ final class Storage { } } } + +extension Storage: StorageType { + func avilableRewards() -> Observable<[ShopItem]> { + return adStorage.availableItems() + } + + func availableMoney() -> Observable { + return gameStorage.availableMoney() + } + + func setNewRewardsIfPossible() -> Observable { + return adStorage.setNewRewardsIfPossible(with: .none) + } + + func rewardNeedsToBeGiven(with finishedAd: GADRewardedAd?) -> Int { + if let finishedAd = finishedAd { + adStorage.adDidFinished(finishedAd) + } else { + adStorage.giftTaken() + } + let reward = ShopSetting.reward() + gameStorage.raiseMoney(by: reward) + return reward + } + + func itemList() -> [Unit] { + return gameStorage.itemList() + } + + func raiseLevel(of unit: Unit, using money: Int) -> Unit { + return gameStorage.raiseLevel(of: unit, using: money) + } + + func myHighScore() -> Int { + return gameStorage.myHighScore() + } + + func raiseMoney(by amount: Int) { + gameStorage.raiseMoney(by: amount) + } + + func updateHighScore(new score: Int) -> Bool { + gameStorage.updateHighScore(new: score) + } + + func save() { + // backUpCenter.save + } +} diff --git a/FullStackCodingBot/FullStackCodingBot/Service/Storage/StorageType.swift b/FullStackCodingBot/FullStackCodingBot/Service/Storage/StorageType.swift new file mode 100644 index 0000000..9528e46 --- /dev/null +++ b/FullStackCodingBot/FullStackCodingBot/Service/Storage/StorageType.swift @@ -0,0 +1,28 @@ +import Foundation +import RxSwift +import GoogleMobileAds + +protocol StorageType { + + func initializeData(using uuid: String?, isFirstLaunched: Bool) -> Observable + + // 우선 나열해보자 + // Shop + func avilableRewards() -> Observable<[ShopItem]> + func availableMoney() -> Observable // + Item + func setNewRewardsIfPossible() -> Observable + func rewardNeedsToBeGiven(with finishedAd: GADRewardedAd?) -> Int + + // Item + func itemList() -> [Unit] + func raiseLevel(of unit: Unit, using money: Int) -> Unit + + // Game + func myHighScore() -> Int + + // GameOver + func raiseMoney(by amount: Int) + func updateHighScore(new score: Int) -> Bool + + func save() +} diff --git a/FullStackCodingBot/FullStackCodingBot/ViewModel/AdViewModel.swift b/FullStackCodingBot/FullStackCodingBot/ViewModel/AdViewModel.swift index 6af6e65..5c38f66 100644 --- a/FullStackCodingBot/FullStackCodingBot/ViewModel/AdViewModel.swift +++ b/FullStackCodingBot/FullStackCodingBot/ViewModel/AdViewModel.swift @@ -1,11 +1,8 @@ import Foundation +// Ad 부분 인터페이스를 나누는 게 나을까? class AdViewModel: CommonViewModel { - - let adStorage: AdStorageType - - init(sceneCoordinator: SceneCoordinatorType, storage: PersistenceStorageType, adStorage: AdStorageType, database: FirebaseManagerType) { - self.adStorage = adStorage - super.init(sceneCoordinator: sceneCoordinator, storage: storage, database: database) + override init(sceneCoordinator: SceneCoordinatorType, storage: StorageType) { + super.init(sceneCoordinator: sceneCoordinator, storage: storage) } } diff --git a/FullStackCodingBot/FullStackCodingBot/ViewModel/CommonViewModel.swift b/FullStackCodingBot/FullStackCodingBot/ViewModel/CommonViewModel.swift index 3aaf3b7..0a38487 100644 --- a/FullStackCodingBot/FullStackCodingBot/ViewModel/CommonViewModel.swift +++ b/FullStackCodingBot/FullStackCodingBot/ViewModel/CommonViewModel.swift @@ -3,12 +3,10 @@ import Foundation class CommonViewModel: NSObject { let sceneCoordinator: SceneCoordinatorType - let storage: PersistenceStorageType - let database: FirebaseManagerType + let storage: StorageType - init(sceneCoordinator: SceneCoordinatorType, storage: PersistenceStorageType, database: FirebaseManagerType) { + init(sceneCoordinator: SceneCoordinatorType, storage: StorageType) { self.sceneCoordinator = sceneCoordinator self.storage = storage - self.database = database } } diff --git a/FullStackCodingBot/FullStackCodingBot/ViewModel/GameOverViewModel.swift b/FullStackCodingBot/FullStackCodingBot/ViewModel/GameOverViewModel.swift index e194dc1..840cfd5 100644 --- a/FullStackCodingBot/FullStackCodingBot/ViewModel/GameOverViewModel.swift +++ b/FullStackCodingBot/FullStackCodingBot/ViewModel/GameOverViewModel.swift @@ -23,12 +23,11 @@ final class GameOverViewModel: CommonViewModel { }() lazy var currentMoney: Driver = { - return storage.availableMoeny().map { String($0) }.asDriver(onErrorJustReturn: "") + return storage.availableMoney().map { String($0) }.asDriver(onErrorJustReturn: "") }() init(sceneCoordinator: SceneCoordinatorType, - storage: PersistenceStorageType, - database: FirebaseManagerType, + storage: StorageType, finalScore: Int, newGameStatus: BehaviorRelay, gameStoryManager: GameStoryManager = GameStoryManager()) { @@ -36,7 +35,7 @@ final class GameOverViewModel: CommonViewModel { self.moneyInfo.accept(finalScore/10) self.newGameStatus = newGameStatus self.gameStoryManager = gameStoryManager - super.init(sceneCoordinator: sceneCoordinator, storage: storage, database: database) + super.init(sceneCoordinator: sceneCoordinator, storage: storage) } func execute() { diff --git a/FullStackCodingBot/FullStackCodingBot/ViewModel/GameViewModel.swift b/FullStackCodingBot/FullStackCodingBot/ViewModel/GameViewModel.swift index cbf0bde..d736ffd 100644 --- a/FullStackCodingBot/FullStackCodingBot/ViewModel/GameViewModel.swift +++ b/FullStackCodingBot/FullStackCodingBot/ViewModel/GameViewModel.swift @@ -33,8 +33,7 @@ final class GameViewModel: CommonViewModel { } init(sceneCoordinator: SceneCoordinatorType, - storage: PersistenceStorageType, - database: FirebaseManagerType, + storage: StorageType, pauseAction: CocoaAction? = nil, gameUnitManager: GameUnitManagerType, timeManager: TimeManagerType = TimeManager(), @@ -42,7 +41,7 @@ final class GameViewModel: CommonViewModel { self.gameUnitManager = gameUnitManager self.timeManager = timeManager self.gameSoundStation = gameSoundStation - super.init(sceneCoordinator: sceneCoordinator, storage: storage, database: database) + super.init(sceneCoordinator: sceneCoordinator, storage: storage) } } @@ -205,7 +204,7 @@ private extension GameViewModel { @discardableResult private func toGameOverScene() -> Completable { let currentScore = try? currentScore.value() - let gameOverViewModel = GameOverViewModel(sceneCoordinator: sceneCoordinator, storage: storage, database: database, finalScore: currentScore ?? 0, newGameStatus: newGameStatus) + let gameOverViewModel = GameOverViewModel(sceneCoordinator: sceneCoordinator, storage: storage, finalScore: currentScore ?? 0, newGameStatus: newGameStatus) let gameOverScene = Scene.gameOver(gameOverViewModel) return self.sceneCoordinator.transition(to: gameOverScene, using: .pop, with: StoryboardType.game, animated: true) } @@ -213,7 +212,7 @@ private extension GameViewModel { @discardableResult private func toPauseScene() -> Completable { let currentScore = try? currentScore.value() - let pauseViewModel = PauseViewModel(sceneCoordinator: sceneCoordinator, storage: storage, database: database, currentScore: currentScore ?? 0, newGameStatus: newGameStatus) + let pauseViewModel = PauseViewModel(sceneCoordinator: sceneCoordinator, storage: storage, currentScore: currentScore ?? 0, newGameStatus: newGameStatus) let pauseScene = Scene.pause(pauseViewModel) return self.sceneCoordinator.transition(to: pauseScene, using: .fullScreen, with: StoryboardType.game, animated: false) } diff --git a/FullStackCodingBot/FullStackCodingBot/ViewModel/HowToPlayViewModel.swift b/FullStackCodingBot/FullStackCodingBot/ViewModel/HowToPlayViewModel.swift index 519c63e..ecfca50 100644 --- a/FullStackCodingBot/FullStackCodingBot/ViewModel/HowToPlayViewModel.swift +++ b/FullStackCodingBot/FullStackCodingBot/ViewModel/HowToPlayViewModel.swift @@ -9,20 +9,14 @@ final class HowToPlayViewModel: CommonViewModel { let currentPage = BehaviorRelay(value: 0) let currentManual = BehaviorRelay(value: Manual.all[0]) - init(sceneCoordinator: SceneCoordinatorType, - storage: PersistenceStorageType, - adStorage: AdStorageType, - database: FirebaseManagerType, - cancelAction: CocoaAction? = nil) { - + init(sceneCoordinator: SceneCoordinatorType, storage: StorageType, cancelAction: CocoaAction? = nil) { self.cancelAction = CocoaAction { if let action = cancelAction { action.execute(()) } return sceneCoordinator.close(animated: true).asObservable().map { _ in } } - - super.init(sceneCoordinator: sceneCoordinator, storage: storage, database: database) + super.init(sceneCoordinator: sceneCoordinator, storage: storage) } func moveToPage(from direction: DirectionType) { diff --git a/FullStackCodingBot/FullStackCodingBot/ViewModel/ItemViewModel.swift b/FullStackCodingBot/FullStackCodingBot/ViewModel/ItemViewModel.swift index 587c453..4b6f78d 100644 --- a/FullStackCodingBot/FullStackCodingBot/ViewModel/ItemViewModel.swift +++ b/FullStackCodingBot/FullStackCodingBot/ViewModel/ItemViewModel.swift @@ -10,11 +10,11 @@ final class ItemViewModel: CommonViewModel { } var itemStorage: Driver<[Unit]> { - return storage.listUnit().asDriver(onErrorJustReturn: []) + return BehaviorRelay<[Unit]>(value: storage.itemList()).asDriver(onErrorJustReturn:[]) } var money: Driver { - return storage.availableMoeny().asDriver(onErrorJustReturn: 0) + return storage.availableMoney().asDriver(onErrorJustReturn: 0) } let isPossibleToLevelUp = BehaviorRelay(value: false) @@ -25,8 +25,7 @@ final class ItemViewModel: CommonViewModel { private let soundEffectStation: SingleSoundEffectStation init(sceneCoordinator: SceneCoordinatorType, - storage: PersistenceStorageType, - database: FirebaseManagerType, + storage: StorageType, cancelAction: CocoaAction? = nil, soundEffectType: MainSoundEffect = .upgrade) { self.cancelAction = CocoaAction { @@ -36,11 +35,11 @@ final class ItemViewModel: CommonViewModel { return sceneCoordinator.close(animated: true).asObservable().map { _ in } } self.soundEffectStation = SingleSoundEffectStation(soundEffectType: soundEffectType) - super.init(sceneCoordinator: sceneCoordinator, storage: storage, database: database) + super.init(sceneCoordinator: sceneCoordinator, storage: storage) } func checkLevelUpPrice() { - storage.availableMoeny() + storage.availableMoney() .subscribe(onNext: { [unowned self] availableMoney in if availableMoney >= (selectedUnit.value.level * 100) { self.isPossibleToLevelUp.accept(true) diff --git a/FullStackCodingBot/FullStackCodingBot/ViewModel/MainViewModel.swift b/FullStackCodingBot/FullStackCodingBot/ViewModel/MainViewModel.swift index 9f144c0..df74d32 100644 --- a/FullStackCodingBot/FullStackCodingBot/ViewModel/MainViewModel.swift +++ b/FullStackCodingBot/FullStackCodingBot/ViewModel/MainViewModel.swift @@ -14,50 +14,35 @@ final class MainViewModel: AdViewModel { let firebaseDidLoad = BehaviorRelay(value: false) private(set) var rewardAvailable = BehaviorRelay(value: false) - // MARK: 임시 선언 - private var newStorage = Storage(gameStorage: FakeGameStorage(), - adStorage: AdStorage(), - backUpCenter: BackUpCenter(firebaseManager: FirebaseManager(), - coreDataManager: FakeCoreDataManager())) - - init(sceneCoordinator: SceneCoordinatorType, storage: PersistenceStorageType, adStorage: AdStorageType, database: FirebaseManagerType, settings: SettingInformation) { + init(sceneCoordinator: SceneCoordinatorType, storage: StorageType, settings: SettingInformation) { self.settingInfo = settings - super.init(sceneCoordinator: sceneCoordinator, storage: storage, adStorage: adStorage, database: database) - - bindRewardState() + super.init(sceneCoordinator: sceneCoordinator, storage: storage) + setupAppleGameCenterLogin() } - - private func bindRewardState() { - adStorage.availableItems() - .subscribe(onNext: { [weak self] items in - let rewardState = !ShopItem.isAllTaken(items) - self?.rewardAvailable.accept(rewardState) - }).disposed(by: rx.disposeBag) - } - + func makeMoveAction(to viewController: ViewControllerType) { guard firebaseDidLoad.value else { return } switch viewController { case .giftVC: - let shopViewModel = ShopViewModel(sceneCoordinator: self.sceneCoordinator, storage: self.storage, adStorage: adStorage, database: database) + let shopViewModel = ShopViewModel(sceneCoordinator: self.sceneCoordinator, storage: self.storage) let shopScene = Scene.shop(shopViewModel) self.sceneCoordinator.transition(to: shopScene, using: .fullScreen, with: StoryboardType.main, animated: true) case .rankVC: - let rankViewModel = RankViewModel(sceneCoordinator: self.sceneCoordinator, storage: self.storage, database: database) + let rankViewModel = RankViewModel(sceneCoordinator: self.sceneCoordinator, storage: self.storage) let rankScene = Scene.rank(rankViewModel) self.sceneCoordinator.transition(to: rankScene, using: .fullScreen, with: StoryboardType.main, animated: true) case .itemVC: - let itemViewModel = ItemViewModel(sceneCoordinator: self.sceneCoordinator, storage: self.storage, database: database) + let itemViewModel = ItemViewModel(sceneCoordinator: self.sceneCoordinator, storage: self.storage) let itemScene = Scene.item(itemViewModel) self.sceneCoordinator.transition(to: itemScene, using: .fullScreen, with: StoryboardType.main, animated: true) case .gameVC: - let gameUnitManager = GameUnitManager(allKinds: self.storage.itemList()) - let gameViewModel = GameViewModel(sceneCoordinator: self.sceneCoordinator, storage: self.storage, database: database, gameUnitManager: gameUnitManager) + let gameUnitManager = GameUnitManager(allKinds: Unit.initialValues()) + let gameViewModel = GameViewModel(sceneCoordinator: self.sceneCoordinator, storage: self.storage, gameUnitManager: gameUnitManager) let gameScene = Scene.game(gameViewModel) self.sceneCoordinator.transition(to: gameScene, using: .fullScreen, with: StoryboardType.game, animated: true) @@ -66,12 +51,12 @@ final class MainViewModel: AdViewModel { self.sceneCoordinator.transition(to: settingScene, using: .overCurrent, with: StoryboardType.main, animated: true) case .storyVC: - let storyViewModel = StoryViewModel(sceneCoordinator: sceneCoordinator, storage: storage, adStorage: adStorage, database: database, settings: settingInfo, isFirstTimePlay: false) + let storyViewModel = StoryViewModel(sceneCoordinator: sceneCoordinator, storage: storage, settings: settingInfo, isFirstTimePlay: false) let storyScene = Scene.story(storyViewModel) self.sceneCoordinator.transition(to: storyScene, using: .fullScreen, with: StoryboardType.main, animated: true) case .howToVC: - let howToViewModel = HowToPlayViewModel(sceneCoordinator: sceneCoordinator, storage: storage, adStorage: adStorage, database: database) + let howToViewModel = HowToPlayViewModel(sceneCoordinator: sceneCoordinator, storage: storage) let howToScene = Scene.howToPlay(howToViewModel) self.sceneCoordinator.transition(to: howToScene, using: .fullScreen, with: StoryboardType.main, animated: true) } @@ -150,7 +135,7 @@ extension MainViewModel { private func load(with uuid: String?) { let isFirstLaunched = !userDefaults.bool(forKey: IdentifierUD.hasLaunchedOnce) - newStorage.initializeData(using: uuid, isFirstLaunched: isFirstLaunched) + storage.initializeData(using: uuid, isFirstLaunched: isFirstLaunched) .observe(on: MainScheduler.asyncInstance) .subscribe(onNext: { [unowned self] isLoaded in self.firebaseDidLoad.accept(isLoaded) diff --git a/FullStackCodingBot/FullStackCodingBot/ViewModel/PauseViewModel.swift b/FullStackCodingBot/FullStackCodingBot/ViewModel/PauseViewModel.swift index 72de88f..8459fec 100644 --- a/FullStackCodingBot/FullStackCodingBot/ViewModel/PauseViewModel.swift +++ b/FullStackCodingBot/FullStackCodingBot/ViewModel/PauseViewModel.swift @@ -11,10 +11,10 @@ final class PauseViewModel: CommonViewModel { return currentScore.map {String($0)}.asDriver(onErrorJustReturn: "") }() - init(sceneCoordinator: SceneCoordinatorType, storage: PersistenceStorageType, database: FirebaseManagerType, currentScore: Int, newGameStatus: BehaviorRelay) { + init(sceneCoordinator: SceneCoordinatorType, storage: StorageType, currentScore: Int, newGameStatus: BehaviorRelay) { self.newGameStatus = newGameStatus self.currentScore.accept(currentScore) - super.init(sceneCoordinator: sceneCoordinator, storage: storage, database: database) + super.init(sceneCoordinator: sceneCoordinator, storage: storage) } func makeMoveAction(to viewController: PauseActionType) { diff --git a/FullStackCodingBot/FullStackCodingBot/ViewModel/RankViewModel.swift b/FullStackCodingBot/FullStackCodingBot/ViewModel/RankViewModel.swift index 2617baf..f82d073 100644 --- a/FullStackCodingBot/FullStackCodingBot/ViewModel/RankViewModel.swift +++ b/FullStackCodingBot/FullStackCodingBot/ViewModel/RankViewModel.swift @@ -6,21 +6,18 @@ final class RankViewModel: CommonViewModel { let cancelAction: CocoaAction - init(sceneCoordinator: SceneCoordinatorType, storage: PersistenceStorageType, database: FirebaseManagerType, cancelAction: CocoaAction? = nil) { - + init(sceneCoordinator: SceneCoordinatorType, storage: StorageType, cancelAction: CocoaAction? = nil) { self.cancelAction = CocoaAction { if let action = cancelAction { action.execute(()) } return sceneCoordinator.close(animated: true).asObservable().map { _ in } } - - super.init(sceneCoordinator: sceneCoordinator, storage: storage, database: database) + super.init(sceneCoordinator: sceneCoordinator, storage: storage) } } extension RankViewModel: GKGameCenterControllerDelegate { - func gameCenterViewControllerDidFinish(_ gameCenterViewController: GKGameCenterViewController) { sceneCoordinator.close(animated: true) } diff --git a/FullStackCodingBot/FullStackCodingBot/ViewModel/ShopViewModel.swift b/FullStackCodingBot/FullStackCodingBot/ViewModel/ShopViewModel.swift index 98c8885..fbf4bc3 100644 --- a/FullStackCodingBot/FullStackCodingBot/ViewModel/ShopViewModel.swift +++ b/FullStackCodingBot/FullStackCodingBot/ViewModel/ShopViewModel.swift @@ -10,11 +10,11 @@ final class ShopViewModel: AdViewModel { let cancelAction: CocoaAction var itemStorage: Driver<[ShopItem]> { - return adStorage.availableItems().asDriver(onErrorJustReturn: []) + return storage.avilableRewards().asDriver(onErrorJustReturn: []) } lazy var currentMoney: Driver = { - return storage.availableMoeny().map {String($0)}.asDriver(onErrorJustReturn: "") + return storage.availableMoney().map { String($0) }.asDriver(onErrorJustReturn: "") }() lazy var selectedItem = BehaviorRelay(value: nil) @@ -22,9 +22,7 @@ final class ShopViewModel: AdViewModel { private let soundEffectStation: SingleSoundEffectStation init(sceneCoordinator: SceneCoordinatorType, - storage: PersistenceStorageType, - adStorage: AdStorageType, - database: FirebaseManagerType, + storage: StorageType, cancelAction: CocoaAction? = nil, soundEffectType: MainSoundEffect = .reward) { self.cancelAction = CocoaAction { @@ -34,7 +32,7 @@ final class ShopViewModel: AdViewModel { return sceneCoordinator.close(animated: true).asObservable().map { _ in } } self.soundEffectStation = SingleSoundEffectStation(soundEffectType: soundEffectType) - super.init(sceneCoordinator: sceneCoordinator, storage: storage, adStorage: adStorage, database: database) + super.init(sceneCoordinator: sceneCoordinator, storage: storage) } func execute() { @@ -42,26 +40,24 @@ final class ShopViewModel: AdViewModel { } private func bindAdStorage() { - adStorage.setNewRewardsIfPossible(with: .none) + storage.setNewRewardsIfPossible() .subscribe(onError: { error in Firebase.Analytics.logEvent("RewardsError", parameters: ["ErrorMessage": "\(error)"])}) .disposed(by: rx.disposeBag) } func adDidFinished(_ finishedAd: GADRewardedAd) { - adStorage.adDidFinished(finishedAd) - addCoin() + let reward = storage.rewardNeedsToBeGiven(with: finishedAd) + addCoin(by: reward) } func giftTaken() { - adStorage.giftTaken() - addCoin() + let reward = storage.rewardNeedsToBeGiven(with: nil) + addCoin(by: reward) } - private func addCoin() { - let moneyToRaise = ShopSetting.reward() - storage.raiseMoney(by: moneyToRaise) - reward.accept(moneyToRaise) + private func addCoin(by amount: Int) { + reward.accept(amount) soundEffectStation.play() } } diff --git a/FullStackCodingBot/FullStackCodingBot/ViewModel/StoryViewModel.swift b/FullStackCodingBot/FullStackCodingBot/ViewModel/StoryViewModel.swift index 4dcd166..55d11f5 100644 --- a/FullStackCodingBot/FullStackCodingBot/ViewModel/StoryViewModel.swift +++ b/FullStackCodingBot/FullStackCodingBot/ViewModel/StoryViewModel.swift @@ -10,16 +10,14 @@ final class StoryViewModel: AdViewModel { private let isFirstTimePlay: Bool init(sceneCoordinator: SceneCoordinatorType, - storage: PersistenceStorageType, - adStorage: AdStorageType, - database: FirebaseManagerType, + storage: StorageType, settings: SettingInformation, storyManger: StoryManager = StoryManager(), isFirstTimePlay: Bool = true) { self.settings = settings self.storyManager = storyManger self.isFirstTimePlay = isFirstTimePlay - super.init(sceneCoordinator: sceneCoordinator, storage: storage, adStorage: adStorage, database: database) + super.init(sceneCoordinator: sceneCoordinator, storage: storage) } func setupStoryTimer() { @@ -46,7 +44,7 @@ final class StoryViewModel: AdViewModel { } private func makeMoveActionToMain() { - let mainViewModel = MainViewModel(sceneCoordinator: sceneCoordinator, storage: storage, adStorage: adStorage, database: database, settings: settings) + let mainViewModel = MainViewModel(sceneCoordinator: sceneCoordinator, storage: storage, settings: settings) let mainScene = Scene.main(mainViewModel) self.sceneCoordinator.transition(to: mainScene, using: .root, with: StoryboardType.main, animated: true) } From 7a98e1c55518e95362f169f213bb4d618d672e96 Mon Sep 17 00:00:00 2001 From: Song Lee Date: Wed, 15 Sep 2021 15:48:46 +0900 Subject: [PATCH 09/17] =?UTF-8?q?refactor:=20[#191]=20Storage=20=EA=B0=9D?= =?UTF-8?q?=EC=B2=B4=20=EC=9D=B4=EB=8B=88=EC=85=9C=EB=9D=BC=EC=9D=B4?= =?UTF-8?q?=EC=A0=80=20=EB=94=94=ED=8F=B4=ED=8A=B8=20=EA=B0=92=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Service/Storage/BackUpManager/BackUpCenter.swift | 3 ++- .../FullStackCodingBot/Service/Storage/Storage.swift | 4 +++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/FullStackCodingBot/FullStackCodingBot/Service/Storage/BackUpManager/BackUpCenter.swift b/FullStackCodingBot/FullStackCodingBot/Service/Storage/BackUpManager/BackUpCenter.swift index 4970d03..fabe6f1 100644 --- a/FullStackCodingBot/FullStackCodingBot/Service/Storage/BackUpManager/BackUpCenter.swift +++ b/FullStackCodingBot/FullStackCodingBot/Service/Storage/BackUpManager/BackUpCenter.swift @@ -6,7 +6,8 @@ final class BackUpCenter: BackUpCenterType { private var firebaseManager: FirebaseManagerType private var coreDataManager: CoreDataManagerType - init(firebaseManager: FirebaseManagerType, coreDataManager: CoreDataManagerType) { + init(firebaseManager: FirebaseManagerType = FirebaseManager(), + coreDataManager: CoreDataManagerType = CoreDataManager()) { self.firebaseManager = firebaseManager self.coreDataManager = coreDataManager } diff --git a/FullStackCodingBot/FullStackCodingBot/Service/Storage/Storage.swift b/FullStackCodingBot/FullStackCodingBot/Service/Storage/Storage.swift index 3d3335a..0deafbc 100644 --- a/FullStackCodingBot/FullStackCodingBot/Service/Storage/Storage.swift +++ b/FullStackCodingBot/FullStackCodingBot/Service/Storage/Storage.swift @@ -8,7 +8,9 @@ final class Storage { private var adStorage: AdStorageType private var backUpCenter: BackUpCenterType - init(gameStorage: GameStorageType, adStorage: AdStorageType, backUpCenter: BackUpCenterType) { + init(gameStorage: GameStorageType = GameStorage(), + adStorage: AdStorageType = AdStorage(), + backUpCenter: BackUpCenterType = BackUpCenter()) { self.gameStorage = gameStorage self.adStorage = adStorage self.backUpCenter = backUpCenter From e7e4f50e9de4fe30beec514812ea152bb1662da8 Mon Sep 17 00:00:00 2001 From: Song Lee Date: Wed, 15 Sep 2021 16:37:41 +0900 Subject: [PATCH 10/17] =?UTF-8?q?refactor:=20[#191]=20=EC=A0=80=EC=9E=A5?= =?UTF-8?q?=20=ED=9D=90=EB=A6=84=20=EC=97=B0=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 각 객체의 저장 기능을 연결지었다 --- .../AppCycle/AppDelegate.swift | 12 ++++----- .../Storage/BackUpManager/BackUpCenter.swift | 12 ++++++++- .../BackUpManager/BackUpCenterType.swift | 6 +++++ .../BackUpManager/CoreDataManager.swift | 14 ++++++++++ .../BackUpManager/CoreDataManagerType.swift | 2 ++ .../Service/Storage/Storage.swift | 27 +++++++++++++------ 6 files changed, 57 insertions(+), 16 deletions(-) diff --git a/FullStackCodingBot/FullStackCodingBot/AppCycle/AppDelegate.swift b/FullStackCodingBot/FullStackCodingBot/AppCycle/AppDelegate.swift index 9ab3de1..a3a6687 100644 --- a/FullStackCodingBot/FullStackCodingBot/AppCycle/AppDelegate.swift +++ b/FullStackCodingBot/FullStackCodingBot/AppCycle/AppDelegate.swift @@ -7,14 +7,12 @@ import AVFoundation class AppDelegate: UIResponder, UIApplicationDelegate { var window: UIWindow? - private let storage: StorageType = Storage(gameStorage: GameStorage(), - adStorage: AdStorage(), - backUpCenter: BackUpCenter(firebaseManager: FirebaseManager(), - coreDataManager: CoreDataManager())) + private var storage: StorageType? private let userDefaults = UserDefaults.standard func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { FirebaseApp.configure() + storage = Storage() setAdMobs() setAudioSession() presentMainViewController() @@ -22,7 +20,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate { } func applicationDidEnterBackground(_ application: UIApplication) { - storage.save() + storage?.save() } } @@ -61,12 +59,12 @@ private extension AppDelegate { switch hasLaunchedOnce { case true: - let mainViewModel = MainViewModel(sceneCoordinator: sceneCoordinator, storage: storage, settings: settings) + let mainViewModel = MainViewModel(sceneCoordinator: sceneCoordinator, storage: storage!, settings: settings) let mainScene = Scene.main(mainViewModel) return mainScene case false: - let storyViewModel = StoryViewModel(sceneCoordinator: sceneCoordinator, storage: storage, settings: settings) + let storyViewModel = StoryViewModel(sceneCoordinator: sceneCoordinator, storage: storage!, settings: settings) let storyScene = Scene.story(storyViewModel) return storyScene diff --git a/FullStackCodingBot/FullStackCodingBot/Service/Storage/BackUpManager/BackUpCenter.swift b/FullStackCodingBot/FullStackCodingBot/Service/Storage/BackUpManager/BackUpCenter.swift index fabe6f1..838c937 100644 --- a/FullStackCodingBot/FullStackCodingBot/Service/Storage/BackUpManager/BackUpCenter.swift +++ b/FullStackCodingBot/FullStackCodingBot/Service/Storage/BackUpManager/BackUpCenter.swift @@ -5,6 +5,7 @@ final class BackUpCenter: BackUpCenterType { private var firebaseManager: FirebaseManagerType private var coreDataManager: CoreDataManagerType + private var disposeBag = DisposeBag() init(firebaseManager: FirebaseManagerType = FirebaseManager(), coreDataManager: CoreDataManagerType = CoreDataManager()) { @@ -27,6 +28,7 @@ final class BackUpCenter: BackUpCenterType { } firebaseManager.load(uuid) + .observe(on: MainScheduler.asyncInstance) .subscribe { onlineData in let onlineUpdate = onlineData.date let localUpdate = localData.date @@ -34,9 +36,17 @@ final class BackUpCenter: BackUpCenterType { observer.onCompleted() } onError: { error in observer.onError(error) - }.dispose() + }.disposed(by: disposeBag) return Disposables.create() } } + + func save(_ newUnit: Unit?, _ newMoney: Int?, _ newScore: Int?) { + coreDataManager.save(newUnit, newMoney, newScore) + } + + func save(_ info: NetworkDTO) { + firebaseManager.save(info) + } } diff --git a/FullStackCodingBot/FullStackCodingBot/Service/Storage/BackUpManager/BackUpCenterType.swift b/FullStackCodingBot/FullStackCodingBot/Service/Storage/BackUpManager/BackUpCenterType.swift index 8e04b9d..10d43e4 100644 --- a/FullStackCodingBot/FullStackCodingBot/Service/Storage/BackUpManager/BackUpCenterType.swift +++ b/FullStackCodingBot/FullStackCodingBot/Service/Storage/BackUpManager/BackUpCenterType.swift @@ -2,5 +2,11 @@ import Foundation import RxSwift protocol BackUpCenterType { + func load(with uuid: String?, _ isFirstLaunched: Bool) -> Observable + + func save(_ newUnit: Unit?, _ newMoney: Int?, _ newScore: Int?) + + func save(_ info: NetworkDTO) + } diff --git a/FullStackCodingBot/FullStackCodingBot/Service/Storage/BackUpManager/CoreDataManager.swift b/FullStackCodingBot/FullStackCodingBot/Service/Storage/BackUpManager/CoreDataManager.swift index 1ec94fa..e6d27d9 100644 --- a/FullStackCodingBot/FullStackCodingBot/Service/Storage/BackUpManager/CoreDataManager.swift +++ b/FullStackCodingBot/FullStackCodingBot/Service/Storage/BackUpManager/CoreDataManager.swift @@ -53,6 +53,20 @@ final class CoreDataManager: CoreDataManagerType { return localData } + func save(_ newUnit: Unit?, _ newMoney: Int?, _ newScore: Int?) { + if let newUnit = newUnit { + try? updateUnit(to: newUnit) + } + + if let newMoney = newMoney { + try? updateMoney(money: newMoney) + } + + if let newScore = newScore { + try? updateScore(score: newScore) + } + } + func lastUpdated() -> Date { let farPastDate = Date.init(timeIntervalSince1970: 0) guard let fetchedInfo = try? fetchMoneyInfo(), diff --git a/FullStackCodingBot/FullStackCodingBot/Service/Storage/BackUpManager/CoreDataManagerType.swift b/FullStackCodingBot/FullStackCodingBot/Service/Storage/BackUpManager/CoreDataManagerType.swift index 8fca98f..5999a03 100644 --- a/FullStackCodingBot/FullStackCodingBot/Service/Storage/BackUpManager/CoreDataManagerType.swift +++ b/FullStackCodingBot/FullStackCodingBot/Service/Storage/BackUpManager/CoreDataManagerType.swift @@ -8,4 +8,6 @@ protocol CoreDataManagerType { func load() -> NetworkDTO? + func save(_ newUnit: Unit?, _ newMoney: Int?, _ newScore: Int?) + } diff --git a/FullStackCodingBot/FullStackCodingBot/Service/Storage/Storage.swift b/FullStackCodingBot/FullStackCodingBot/Service/Storage/Storage.swift index 0deafbc..423e752 100644 --- a/FullStackCodingBot/FullStackCodingBot/Service/Storage/Storage.swift +++ b/FullStackCodingBot/FullStackCodingBot/Service/Storage/Storage.swift @@ -7,6 +7,7 @@ final class Storage { private var gameStorage: GameStorageType private var adStorage: AdStorageType private var backUpCenter: BackUpCenterType + private var disposeBag = DisposeBag() init(gameStorage: GameStorageType = GameStorage(), adStorage: AdStorageType = AdStorage(), @@ -17,17 +18,18 @@ final class Storage { } func initializeData(using uuid: String?, isFirstLaunched: Bool) -> Observable { - Observable.create { [weak self] observer in - self?.backUpCenter.load(with: uuid, isFirstLaunched) + Observable.create { [unowned self] observer in + self.backUpCenter.load(with: uuid, isFirstLaunched) .observe(on: MainScheduler.asyncInstance) .subscribe(onNext: { data in - self?.gameStorage.update(with: data) - self?.adStorage.setNewRewardsIfPossible(with: data.ads) + self.gameStorage.update(with: data) + self.adStorage.setNewRewardsIfPossible(with: data.ads) + observer.onNext(true) }, onError: { _ in observer.onNext(false) }, onCompleted: { observer.onNext(true) - }).dispose() + }).disposed(by: self.disposeBag) return Disposables.create() } } @@ -62,7 +64,9 @@ extension Storage: StorageType { } func raiseLevel(of unit: Unit, using money: Int) -> Unit { - return gameStorage.raiseLevel(of: unit, using: money) + let newUnit = gameStorage.raiseLevel(of: unit, using: money) + backUpCenter.save(newUnit, .none, .none) + return newUnit } func myHighScore() -> Int { @@ -71,13 +75,20 @@ extension Storage: StorageType { func raiseMoney(by amount: Int) { gameStorage.raiseMoney(by: amount) + backUpCenter.save(.none, gameStorage.myMoney(), .none) } func updateHighScore(new score: Int) -> Bool { - gameStorage.updateHighScore(new: score) + backUpCenter.save(.none, .none, score) + return gameStorage.updateHighScore(new: score) } func save() { - // backUpCenter.save + let currentData = NetworkDTO(units: gameStorage.itemList(), + money: gameStorage.myMoney(), + score: gameStorage.myHighScore(), + ads: adStorage.currentInformation(), + date: Date()) + backUpCenter.save(currentData) } } From 49093f5c4abf56e1ee5cf3f4703b0aacb21eaa23 Mon Sep 17 00:00:00 2001 From: Song Lee Date: Wed, 15 Sep 2021 16:42:44 +0900 Subject: [PATCH 11/17] =?UTF-8?q?refactor:=20[#191]=20=EB=B6=88=ED=95=84?= =?UTF-8?q?=EC=9A=94=ED=95=9C=20=EB=A9=94=EC=86=8C=EB=93=9C=20=EC=A0=9C?= =?UTF-8?q?=EA=B1=B0,=20=EC=8B=A4=EC=88=98=EB=A1=9C=20=EC=A7=80=EC=9A=B4?= =?UTF-8?q?=20=EB=A9=94=EC=86=8C=EB=93=9C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Storage/BackUpManager/CoreDataManager.swift | 10 ---------- .../FullStackCodingBot/ViewModel/MainViewModel.swift | 9 +++++++++ 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/FullStackCodingBot/FullStackCodingBot/Service/Storage/BackUpManager/CoreDataManager.swift b/FullStackCodingBot/FullStackCodingBot/Service/Storage/BackUpManager/CoreDataManager.swift index e6d27d9..a84066a 100644 --- a/FullStackCodingBot/FullStackCodingBot/Service/Storage/BackUpManager/CoreDataManager.swift +++ b/FullStackCodingBot/FullStackCodingBot/Service/Storage/BackUpManager/CoreDataManager.swift @@ -66,16 +66,6 @@ final class CoreDataManager: CoreDataManagerType { try? updateScore(score: newScore) } } - - func lastUpdated() -> Date { - let farPastDate = Date.init(timeIntervalSince1970: 0) - guard let fetchedInfo = try? fetchMoneyInfo(), - let currentMoneyInfo = fetchedInfo.first else { - return farPastDate - } - let lastUpdated = currentMoneyInfo.lastUpdated ?? farPastDate - return lastUpdated - } } // MARK: new diff --git a/FullStackCodingBot/FullStackCodingBot/ViewModel/MainViewModel.swift b/FullStackCodingBot/FullStackCodingBot/ViewModel/MainViewModel.swift index df74d32..9df6d0c 100644 --- a/FullStackCodingBot/FullStackCodingBot/ViewModel/MainViewModel.swift +++ b/FullStackCodingBot/FullStackCodingBot/ViewModel/MainViewModel.swift @@ -18,9 +18,18 @@ final class MainViewModel: AdViewModel { self.settingInfo = settings super.init(sceneCoordinator: sceneCoordinator, storage: storage) + bindRewarsStates() setupAppleGameCenterLogin() } + private func bindRewarsStates() { + storage.avilableRewards() + .subscribe(onNext: { [weak self] items in + let rewardState = !ShopItem.isAllTaken(items) + self?.rewardAvailable.accept(rewardState) + }).disposed(by: rx.disposeBag) + } + func makeMoveAction(to viewController: ViewControllerType) { guard firebaseDidLoad.value else { return } From 0c29d776f45a81270551a2ac6182f0ca88b885c9 Mon Sep 17 00:00:00 2001 From: Song Lee Date: Wed, 15 Sep 2021 17:01:20 +0900 Subject: [PATCH 12/17] =?UTF-8?q?fix:=20[#191]=20=EB=A6=AC=EC=9B=8C?= =?UTF-8?q?=EB=93=9C=20=EB=8F=99=EA=B8=B0=ED=99=94=20=EB=AC=B8=EC=A0=9C=20?= =?UTF-8?q?=ED=95=B4=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 빠진 구독 추가 --- .../FullStackCodingBot/Service/Storage/Storage.swift | 1 + 1 file changed, 1 insertion(+) diff --git a/FullStackCodingBot/FullStackCodingBot/Service/Storage/Storage.swift b/FullStackCodingBot/FullStackCodingBot/Service/Storage/Storage.swift index 423e752..de1d9d8 100644 --- a/FullStackCodingBot/FullStackCodingBot/Service/Storage/Storage.swift +++ b/FullStackCodingBot/FullStackCodingBot/Service/Storage/Storage.swift @@ -24,6 +24,7 @@ final class Storage { .subscribe(onNext: { data in self.gameStorage.update(with: data) self.adStorage.setNewRewardsIfPossible(with: data.ads) + .subscribe(onError: { _ in }).disposed(by: disposeBag) observer.onNext(true) }, onError: { _ in observer.onNext(false) From 1949c99b554beb798fb7aa2be0d30c1766ab010b Mon Sep 17 00:00:00 2001 From: Song Lee Date: Wed, 15 Sep 2021 17:03:13 +0900 Subject: [PATCH 13/17] =?UTF-8?q?chore:=20[#191]=20=EC=98=A4=ED=83=80,=20?= =?UTF-8?q?=EC=BD=94=EB=A9=98=ED=8A=B8=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../FullStackCodingBot/Service/Storage/Storage.swift | 2 +- .../FullStackCodingBot/Service/Storage/StorageType.swift | 4 ++-- .../FullStackCodingBot/ViewModel/MainViewModel.swift | 6 +++--- .../FullStackCodingBot/ViewModel/ShopViewModel.swift | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/FullStackCodingBot/FullStackCodingBot/Service/Storage/Storage.swift b/FullStackCodingBot/FullStackCodingBot/Service/Storage/Storage.swift index de1d9d8..a5b0aec 100644 --- a/FullStackCodingBot/FullStackCodingBot/Service/Storage/Storage.swift +++ b/FullStackCodingBot/FullStackCodingBot/Service/Storage/Storage.swift @@ -37,7 +37,7 @@ final class Storage { } extension Storage: StorageType { - func avilableRewards() -> Observable<[ShopItem]> { + func availableRewards() -> Observable<[ShopItem]> { return adStorage.availableItems() } diff --git a/FullStackCodingBot/FullStackCodingBot/Service/Storage/StorageType.swift b/FullStackCodingBot/FullStackCodingBot/Service/Storage/StorageType.swift index 9528e46..235f35d 100644 --- a/FullStackCodingBot/FullStackCodingBot/Service/Storage/StorageType.swift +++ b/FullStackCodingBot/FullStackCodingBot/Service/Storage/StorageType.swift @@ -6,9 +6,8 @@ protocol StorageType { func initializeData(using uuid: String?, isFirstLaunched: Bool) -> Observable - // 우선 나열해보자 // Shop - func avilableRewards() -> Observable<[ShopItem]> + func availableRewards() -> Observable<[ShopItem]> func availableMoney() -> Observable // + Item func setNewRewardsIfPossible() -> Observable func rewardNeedsToBeGiven(with finishedAd: GADRewardedAd?) -> Int @@ -24,5 +23,6 @@ protocol StorageType { func raiseMoney(by amount: Int) func updateHighScore(new score: Int) -> Bool + // Background func save() } diff --git a/FullStackCodingBot/FullStackCodingBot/ViewModel/MainViewModel.swift b/FullStackCodingBot/FullStackCodingBot/ViewModel/MainViewModel.swift index 9df6d0c..5ee9e1d 100644 --- a/FullStackCodingBot/FullStackCodingBot/ViewModel/MainViewModel.swift +++ b/FullStackCodingBot/FullStackCodingBot/ViewModel/MainViewModel.swift @@ -18,12 +18,12 @@ final class MainViewModel: AdViewModel { self.settingInfo = settings super.init(sceneCoordinator: sceneCoordinator, storage: storage) - bindRewarsStates() + bindRewardStates() setupAppleGameCenterLogin() } - private func bindRewarsStates() { - storage.avilableRewards() + private func bindRewardStates() { + storage.availableRewards() .subscribe(onNext: { [weak self] items in let rewardState = !ShopItem.isAllTaken(items) self?.rewardAvailable.accept(rewardState) diff --git a/FullStackCodingBot/FullStackCodingBot/ViewModel/ShopViewModel.swift b/FullStackCodingBot/FullStackCodingBot/ViewModel/ShopViewModel.swift index fbf4bc3..d5ffab9 100644 --- a/FullStackCodingBot/FullStackCodingBot/ViewModel/ShopViewModel.swift +++ b/FullStackCodingBot/FullStackCodingBot/ViewModel/ShopViewModel.swift @@ -10,7 +10,7 @@ final class ShopViewModel: AdViewModel { let cancelAction: CocoaAction var itemStorage: Driver<[ShopItem]> { - return storage.avilableRewards().asDriver(onErrorJustReturn: []) + return storage.availableRewards().asDriver(onErrorJustReturn: []) } lazy var currentMoney: Driver = { From 20082ba25fe66c8e3a694c39bb1be0bf9e756d71 Mon Sep 17 00:00:00 2001 From: Song Lee Date: Wed, 15 Sep 2021 17:12:06 +0900 Subject: [PATCH 14/17] =?UTF-8?q?fix:=20[#191]=20=EB=B9=A0=EC=A7=84=20?= =?UTF-8?q?=EC=A0=80=EC=9E=A5=20=EA=B5=AC=EB=AC=B8=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../FullStackCodingBot/Service/Storage/Storage.swift | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/FullStackCodingBot/FullStackCodingBot/Service/Storage/Storage.swift b/FullStackCodingBot/FullStackCodingBot/Service/Storage/Storage.swift index a5b0aec..c8d5e49 100644 --- a/FullStackCodingBot/FullStackCodingBot/Service/Storage/Storage.swift +++ b/FullStackCodingBot/FullStackCodingBot/Service/Storage/Storage.swift @@ -57,6 +57,7 @@ extension Storage: StorageType { } let reward = ShopSetting.reward() gameStorage.raiseMoney(by: reward) + backUpCenter.save(.none, gameStorage.myMoney(), .none) return reward } @@ -66,7 +67,7 @@ extension Storage: StorageType { func raiseLevel(of unit: Unit, using money: Int) -> Unit { let newUnit = gameStorage.raiseLevel(of: unit, using: money) - backUpCenter.save(newUnit, .none, .none) + backUpCenter.save(newUnit, gameStorage.myMoney(), .none) return newUnit } @@ -80,8 +81,9 @@ extension Storage: StorageType { } func updateHighScore(new score: Int) -> Bool { - backUpCenter.save(.none, .none, score) - return gameStorage.updateHighScore(new: score) + let isUpdatable = gameStorage.updateHighScore(new: score) + if isUpdatable { backUpCenter.save(.none, .none, score) } + return isUpdatable } func save() { From b4ba872f7c19af9af7e56e71f19f7729a76f7686 Mon Sep 17 00:00:00 2001 From: Song Lee Date: Wed, 15 Sep 2021 17:21:44 +0900 Subject: [PATCH 15/17] =?UTF-8?q?refactor:=20[#191]=20=ED=94=84=EB=A1=9C?= =?UTF-8?q?=ED=8D=BC=ED=8B=B0=20=EC=9D=B4=EB=A6=84=20=EB=B3=80=EA=B2=BD,?= =?UTF-8?q?=20=ED=98=B8=EC=B6=9C=20=EC=9C=84=EC=B9=98=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ViewController/Main/MainViewController.swift | 2 +- .../ViewModel/MainViewModel.swift | 15 +++++++-------- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/FullStackCodingBot/FullStackCodingBot/View/Controller/ViewController/Main/MainViewController.swift b/FullStackCodingBot/FullStackCodingBot/View/Controller/ViewController/Main/MainViewController.swift index 41a9bfa..d4db0d6 100644 --- a/FullStackCodingBot/FullStackCodingBot/View/Controller/ViewController/Main/MainViewController.swift +++ b/FullStackCodingBot/FullStackCodingBot/View/Controller/ViewController/Main/MainViewController.swift @@ -42,7 +42,7 @@ final class MainViewController: UIViewController, ViewModelBindableType { self.viewModel.makeMoveAction(to: viewController) } - viewModel.firebaseDidLoad + viewModel.storageDidSetup .subscribe(onNext: { [unowned self] isLoaded in guard isLoaded else { return } self.unsetLoadingView() diff --git a/FullStackCodingBot/FullStackCodingBot/ViewModel/MainViewModel.swift b/FullStackCodingBot/FullStackCodingBot/ViewModel/MainViewModel.swift index 5ee9e1d..ec00680 100644 --- a/FullStackCodingBot/FullStackCodingBot/ViewModel/MainViewModel.swift +++ b/FullStackCodingBot/FullStackCodingBot/ViewModel/MainViewModel.swift @@ -11,7 +11,7 @@ final class MainViewModel: AdViewModel { private let userDefaults = UserDefaults.standard lazy var settingSwitchState = BehaviorRelay(value: settingInfo) - let firebaseDidLoad = BehaviorRelay(value: false) + let storageDidSetup = BehaviorRelay(value: false) private(set) var rewardAvailable = BehaviorRelay(value: false) init(sceneCoordinator: SceneCoordinatorType, storage: StorageType, settings: SettingInformation) { @@ -31,7 +31,7 @@ final class MainViewModel: AdViewModel { } func makeMoveAction(to viewController: ViewControllerType) { - guard firebaseDidLoad.value else { return } + guard storageDidSetup.value else { return } switch viewController { case .giftVC: @@ -99,9 +99,6 @@ extension MainViewModel: GKGameCenterControllerDelegate { private func setupAppleGameCenterLogin() { GKLocalPlayer.local.authenticateHandler = { [unowned self] gcViewController, error in - - guard !self.firebaseDidLoad.value else { return } - if let gcViewController = gcViewController { let scene = Scene.gameCenter(gcViewController) self.sceneCoordinator.transition(to: scene, using: .fullScreen, with: StoryboardType.main, animated: false) @@ -139,15 +136,17 @@ extension MainViewModel: GKGameCenterControllerDelegate { } } -// MARK: Storage Read +// MARK: Storage Load extension MainViewModel { private func load(with uuid: String?) { + guard !self.storageDidSetup.value else { return } + let isFirstLaunched = !userDefaults.bool(forKey: IdentifierUD.hasLaunchedOnce) storage.initializeData(using: uuid, isFirstLaunched: isFirstLaunched) .observe(on: MainScheduler.asyncInstance) - .subscribe(onNext: { [unowned self] isLoaded in - self.firebaseDidLoad.accept(isLoaded) + .subscribe(onNext: { [unowned self] isInitialized in + self.storageDidSetup.accept(isInitialized) }).disposed(by: rx.disposeBag) markAsLauncedOnce() From 264a8d4bb08fb64b51b4267ea9e218f88dba4131 Mon Sep 17 00:00:00 2001 From: Song Lee Date: Thu, 23 Sep 2021 13:50:57 +0900 Subject: [PATCH 16/17] =?UTF-8?q?refactor:=20[#191]=20Storage=20Key=20?= =?UTF-8?q?=EA=B0=92=20=EC=83=81=EC=88=98=20=EC=A0=95=EC=9D=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../BackUpManager/CoreDataManager.swift | 49 +++++++++++++------ .../BackUpManager/FirebaseManager.swift | 19 ++++++- 2 files changed, 50 insertions(+), 18 deletions(-) diff --git a/FullStackCodingBot/FullStackCodingBot/Service/Storage/BackUpManager/CoreDataManager.swift b/FullStackCodingBot/FullStackCodingBot/Service/Storage/BackUpManager/CoreDataManager.swift index a84066a..29a0afc 100644 --- a/FullStackCodingBot/FullStackCodingBot/Service/Storage/BackUpManager/CoreDataManager.swift +++ b/FullStackCodingBot/FullStackCodingBot/Service/Storage/BackUpManager/CoreDataManager.swift @@ -4,8 +4,10 @@ import RxSwift final class CoreDataManager: CoreDataManagerType { + private let storageKey = "CoreDataStorage" + private lazy var persistentContainer: NSPersistentContainer = { - let container = NSPersistentContainer(name: "CoreDataStorage") + let container = NSPersistentContainer(name: storageKey) container.loadPersistentStores { _, error in if let error = error { fatalError() @@ -18,6 +20,21 @@ final class CoreDataManager: CoreDataManagerType { return persistentContainer.viewContext } + enum Entity { + static let item = "ItemInformation" + static let money = "MoneyInformation" + static let score = "ScoreInformation" + } + + enum Keys { + static let uuid = "uuid" + static let image = "image" + static let level = "level" + static let myMoney = "myMoney" + static let lastUpdated = "lastUpdated" + static let myScore = "myScore" + } + @discardableResult func setupInitialData() -> Completable { let subject = PublishSubject() @@ -75,11 +92,11 @@ extension CoreDataManager { guard fetchedUnit == nil else { return } try units.forEach { unit in - if let entity = NSEntityDescription.entity(forEntityName: "ItemInformation", in: context) { + if let entity = NSEntityDescription.entity(forEntityName: Entity.item, in: context) { let info = NSManagedObject(entity: entity, insertInto: context) - info.setValue(unit.uuid, forKey: "uuid") - info.setValue(unit.image, forKey: "image") - info.setValue(unit.level, forKey: "level") + info.setValue(unit.uuid, forKey: Keys.uuid) + info.setValue(unit.image, forKey: Keys.image) + info.setValue(unit.level, forKey: Keys.level) do { try context.save() @@ -94,10 +111,10 @@ extension CoreDataManager { let fetchedMoney = try? fetchMoneyInfo().first guard fetchedMoney == nil else { return } - if let entity = NSEntityDescription.entity(forEntityName: "MoneyInformation", in: context) { + if let entity = NSEntityDescription.entity(forEntityName: Entity.money, in: context) { let info = NSManagedObject(entity: entity, insertInto: context) - info.setValue(money, forKey: "myMoney") - info.setValue(Date.init(timeIntervalSince1970: 0), forKey: "lastUpdated") + info.setValue(money, forKey: Keys.myMoney) + info.setValue(Date.init(timeIntervalSince1970: 0), forKey: Keys.lastUpdated) do { try context.save() @@ -111,9 +128,9 @@ extension CoreDataManager { let fetchedScore = try? fetchScoreInfo().first guard fetchedScore == nil else { return } - if let entity = NSEntityDescription.entity(forEntityName: "ScoreInformation", in: context) { + if let entity = NSEntityDescription.entity(forEntityName: Entity.score, in: context) { let info = NSManagedObject(entity: entity, insertInto: context) - info.setValue(score, forKey: "myScore") + info.setValue(score, forKey: Keys.myScore) do { try context.save() @@ -164,9 +181,9 @@ extension CoreDataManager { guard let fetchedUnit = try? fetchUnit() else { return } for info in fetchedUnit where info.uuid == unit.uuid { - info.setValue(unit.uuid, forKey: "uuid") - info.setValue(unit.image, forKey: "image") - info.setValue(unit.level, forKey: "level") + info.setValue(unit.uuid, forKey: Keys.uuid) + info.setValue(unit.image, forKey: Keys.image) + info.setValue(unit.level, forKey: Keys.level) } do { @@ -179,8 +196,8 @@ extension CoreDataManager { private func updateMoney(money: Int) throws { do { let previousInfo = try fetchMoneyInfo().first ?? MoneyInformation(context: context) - previousInfo.setValue(money, forKey: "myMoney") - previousInfo.setValue(Date(), forKey: "lastUpdated") + previousInfo.setValue(money, forKey: Keys.myMoney) + previousInfo.setValue(Date(), forKey: Keys.lastUpdated) try context.save() } catch { throw CoreDataError.cannotSaveData @@ -190,7 +207,7 @@ extension CoreDataManager { private func updateScore(score: Int) throws { do { let previousInfo = try fetchScoreInfo().first ?? ScoreInformation(context: context) - previousInfo.setValue(score, forKey: "myScore") + previousInfo.setValue(score, forKey: Keys.myScore) try context.save() } catch { throw CoreDataError.cannotSaveData diff --git a/FullStackCodingBot/FullStackCodingBot/Service/Storage/BackUpManager/FirebaseManager.swift b/FullStackCodingBot/FullStackCodingBot/Service/Storage/BackUpManager/FirebaseManager.swift index 76d7a45..aa6304c 100644 --- a/FullStackCodingBot/FullStackCodingBot/Service/Storage/BackUpManager/FirebaseManager.swift +++ b/FullStackCodingBot/FullStackCodingBot/Service/Storage/BackUpManager/FirebaseManager.swift @@ -8,6 +8,16 @@ final class FirebaseManager: FirebaseManagerType { private let uid = Auth.auth().currentUser?.uid ?? "" private let disposedBag = DisposeBag() + enum Keys { + static let users = "users" + static let info = "info" + static let units = "units" + static let money = "money" + static let score = "score" + static let ads = "ads" + static let date = "date" + } + init(_ ref: DatabaseReference = Database.database().reference()) { self.ref = ref } @@ -20,13 +30,18 @@ final class FirebaseManager: FirebaseManagerType { let scoreData = try? DataFormatManager.transformToString(info.score) let adsData = try? DataFormatManager.transformToString(info.ads) let recentDate = try? DataFormatManager.transformToString(info.date) - ref.child("users").child(uid).setValue(["info": ["units": unitData, "money": moneyData, "score": scoreData, "ads": adsData, "date": recentDate]]) + + ref.child(Keys.users).child(uid).setValue([Keys.info: [Keys.units: unitData, + Keys.money: moneyData, + Keys.score: scoreData, + Keys.ads: adsData, + Keys.date: recentDate]]) } @discardableResult func load(_ uuid: String) -> Observable { Observable.create { [unowned self] observer in - self.ref.child("users").child(uuid).getData { error, snapshot in + self.ref.child(Keys.users).child(uuid).getData { error, snapshot in if let error = error { observer.onError(error) } From 4999cf0cce654ae4e04e715dc47610815df7d260 Mon Sep 17 00:00:00 2001 From: Song Lee Date: Thu, 23 Sep 2021 14:23:52 +0900 Subject: [PATCH 17/17] =?UTF-8?q?refactor:=20[#191]=20=EA=B0=80=EB=8F=85?= =?UTF-8?q?=EC=84=B1=20=EA=B0=9C=EC=84=A0=EC=9D=84=20=EC=9C=84=ED=95=9C=20?= =?UTF-8?q?=EB=A7=A4=EA=B0=9C=EB=B3=80=EC=88=98=20=EB=AA=85=EC=B9=AD=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Storage/BackUpManager/BackUpCenter.swift | 10 +++++----- .../Storage/BackUpManager/BackUpCenterType.swift | 4 ++-- .../Storage/BackUpManager/CoreDataManager.swift | 2 +- .../BackUpManager/CoreDataManagerType.swift | 2 +- .../Storage/BackUpManager/FirebaseManager.swift | 14 +++++++------- .../BackUpManager/FirebaseManagerType.swift | 4 ++-- .../Service/Storage/Storage.swift | 10 +++++----- 7 files changed, 23 insertions(+), 23 deletions(-) diff --git a/FullStackCodingBot/FullStackCodingBot/Service/Storage/BackUpManager/BackUpCenter.swift b/FullStackCodingBot/FullStackCodingBot/Service/Storage/BackUpManager/BackUpCenter.swift index 838c937..192255a 100644 --- a/FullStackCodingBot/FullStackCodingBot/Service/Storage/BackUpManager/BackUpCenter.swift +++ b/FullStackCodingBot/FullStackCodingBot/Service/Storage/BackUpManager/BackUpCenter.swift @@ -27,7 +27,7 @@ final class BackUpCenter: BackUpCenterType { return Disposables.create() } - firebaseManager.load(uuid) + firebaseManager.load(with: uuid) .observe(on: MainScheduler.asyncInstance) .subscribe { onlineData in let onlineUpdate = onlineData.date @@ -42,11 +42,11 @@ final class BackUpCenter: BackUpCenterType { } } - func save(_ newUnit: Unit?, _ newMoney: Int?, _ newScore: Int?) { - coreDataManager.save(newUnit, newMoney, newScore) + func save(gameData newUnit: Unit?, _ newMoney: Int?, _ newScore: Int?) { + coreDataManager.save(gameData: newUnit, newMoney, newScore) } - func save(_ info: NetworkDTO) { - firebaseManager.save(info) + func save(gameData: NetworkDTO) { + firebaseManager.save(gameData: gameData) } } diff --git a/FullStackCodingBot/FullStackCodingBot/Service/Storage/BackUpManager/BackUpCenterType.swift b/FullStackCodingBot/FullStackCodingBot/Service/Storage/BackUpManager/BackUpCenterType.swift index 10d43e4..9f59d94 100644 --- a/FullStackCodingBot/FullStackCodingBot/Service/Storage/BackUpManager/BackUpCenterType.swift +++ b/FullStackCodingBot/FullStackCodingBot/Service/Storage/BackUpManager/BackUpCenterType.swift @@ -5,8 +5,8 @@ protocol BackUpCenterType { func load(with uuid: String?, _ isFirstLaunched: Bool) -> Observable - func save(_ newUnit: Unit?, _ newMoney: Int?, _ newScore: Int?) + func save(gameData newUnit: Unit?, _ newMoney: Int?, _ newScore: Int?) - func save(_ info: NetworkDTO) + func save(gameData: NetworkDTO) } diff --git a/FullStackCodingBot/FullStackCodingBot/Service/Storage/BackUpManager/CoreDataManager.swift b/FullStackCodingBot/FullStackCodingBot/Service/Storage/BackUpManager/CoreDataManager.swift index 29a0afc..aa844e1 100644 --- a/FullStackCodingBot/FullStackCodingBot/Service/Storage/BackUpManager/CoreDataManager.swift +++ b/FullStackCodingBot/FullStackCodingBot/Service/Storage/BackUpManager/CoreDataManager.swift @@ -70,7 +70,7 @@ final class CoreDataManager: CoreDataManagerType { return localData } - func save(_ newUnit: Unit?, _ newMoney: Int?, _ newScore: Int?) { + func save(gameData newUnit: Unit?, _ newMoney: Int?, _ newScore: Int?) { if let newUnit = newUnit { try? updateUnit(to: newUnit) } diff --git a/FullStackCodingBot/FullStackCodingBot/Service/Storage/BackUpManager/CoreDataManagerType.swift b/FullStackCodingBot/FullStackCodingBot/Service/Storage/BackUpManager/CoreDataManagerType.swift index 5999a03..548768b 100644 --- a/FullStackCodingBot/FullStackCodingBot/Service/Storage/BackUpManager/CoreDataManagerType.swift +++ b/FullStackCodingBot/FullStackCodingBot/Service/Storage/BackUpManager/CoreDataManagerType.swift @@ -8,6 +8,6 @@ protocol CoreDataManagerType { func load() -> NetworkDTO? - func save(_ newUnit: Unit?, _ newMoney: Int?, _ newScore: Int?) + func save(gameData newUnit: Unit?, _ newMoney: Int?, _ newScore: Int?) } diff --git a/FullStackCodingBot/FullStackCodingBot/Service/Storage/BackUpManager/FirebaseManager.swift b/FullStackCodingBot/FullStackCodingBot/Service/Storage/BackUpManager/FirebaseManager.swift index aa6304c..d8b8029 100644 --- a/FullStackCodingBot/FullStackCodingBot/Service/Storage/BackUpManager/FirebaseManager.swift +++ b/FullStackCodingBot/FullStackCodingBot/Service/Storage/BackUpManager/FirebaseManager.swift @@ -22,14 +22,14 @@ final class FirebaseManager: FirebaseManagerType { self.ref = ref } - func save(_ info: NetworkDTO) { + func save(gameData: NetworkDTO) { guard uid != "" else { return } - let unitData = try? DataFormatManager.transformToString(info.units) - let moneyData = try? DataFormatManager.transformToString(info.money) - let scoreData = try? DataFormatManager.transformToString(info.score) - let adsData = try? DataFormatManager.transformToString(info.ads) - let recentDate = try? DataFormatManager.transformToString(info.date) + let unitData = try? DataFormatManager.transformToString(gameData.units) + let moneyData = try? DataFormatManager.transformToString(gameData.money) + let scoreData = try? DataFormatManager.transformToString(gameData.score) + let adsData = try? DataFormatManager.transformToString(gameData.ads) + let recentDate = try? DataFormatManager.transformToString(gameData.date) ref.child(Keys.users).child(uid).setValue([Keys.info: [Keys.units: unitData, Keys.money: moneyData, @@ -39,7 +39,7 @@ final class FirebaseManager: FirebaseManagerType { } @discardableResult - func load(_ uuid: String) -> Observable { + func load(with uuid: String) -> Observable { Observable.create { [unowned self] observer in self.ref.child(Keys.users).child(uuid).getData { error, snapshot in if let error = error { diff --git a/FullStackCodingBot/FullStackCodingBot/Service/Storage/BackUpManager/FirebaseManagerType.swift b/FullStackCodingBot/FullStackCodingBot/Service/Storage/BackUpManager/FirebaseManagerType.swift index 4b78ea5..0337a1c 100644 --- a/FullStackCodingBot/FullStackCodingBot/Service/Storage/BackUpManager/FirebaseManagerType.swift +++ b/FullStackCodingBot/FullStackCodingBot/Service/Storage/BackUpManager/FirebaseManagerType.swift @@ -4,7 +4,7 @@ import RxSwift protocol FirebaseManagerType { @discardableResult - func load(_ uuid: String) -> Observable + func load(with uuid: String) -> Observable - func save(_ info: NetworkDTO) + func save(gameData: NetworkDTO) } diff --git a/FullStackCodingBot/FullStackCodingBot/Service/Storage/Storage.swift b/FullStackCodingBot/FullStackCodingBot/Service/Storage/Storage.swift index c8d5e49..482647a 100644 --- a/FullStackCodingBot/FullStackCodingBot/Service/Storage/Storage.swift +++ b/FullStackCodingBot/FullStackCodingBot/Service/Storage/Storage.swift @@ -57,7 +57,7 @@ extension Storage: StorageType { } let reward = ShopSetting.reward() gameStorage.raiseMoney(by: reward) - backUpCenter.save(.none, gameStorage.myMoney(), .none) + backUpCenter.save(gameData: .none, gameStorage.myMoney(), .none) return reward } @@ -67,7 +67,7 @@ extension Storage: StorageType { func raiseLevel(of unit: Unit, using money: Int) -> Unit { let newUnit = gameStorage.raiseLevel(of: unit, using: money) - backUpCenter.save(newUnit, gameStorage.myMoney(), .none) + backUpCenter.save(gameData: newUnit, gameStorage.myMoney(), .none) return newUnit } @@ -77,12 +77,12 @@ extension Storage: StorageType { func raiseMoney(by amount: Int) { gameStorage.raiseMoney(by: amount) - backUpCenter.save(.none, gameStorage.myMoney(), .none) + backUpCenter.save(gameData: .none, gameStorage.myMoney(), .none) } func updateHighScore(new score: Int) -> Bool { let isUpdatable = gameStorage.updateHighScore(new: score) - if isUpdatable { backUpCenter.save(.none, .none, score) } + if isUpdatable { backUpCenter.save(gameData: .none, .none, score) } return isUpdatable } @@ -92,6 +92,6 @@ extension Storage: StorageType { score: gameStorage.myHighScore(), ads: adStorage.currentInformation(), date: Date()) - backUpCenter.save(currentData) + backUpCenter.save(gameData: currentData) } }