diff --git a/iOS/Features/Home/Sources/Home/Presentation/HomeViewModel.swift b/iOS/Features/Home/Sources/Home/Presentation/HomeViewModel.swift index 559795b..79a6a1d 100644 --- a/iOS/Features/Home/Sources/Home/Presentation/HomeViewModel.swift +++ b/iOS/Features/Home/Sources/Home/Presentation/HomeViewModel.swift @@ -68,16 +68,12 @@ public final class HomeViewModel { func trigger(_ action: Action) { switch action { case .viewNeedsLoaded: -// #if DEBUG -// self.isFirstLaunch = true -// try? self.keychain.deleteAll() -// #endif + #if DEBUG let firstLaunchMessage = self.isFirstLaunch ? "앱이 처음 실행되었습니다." : "앱 첫 실행이 아닙니다." - MSLogger.make(category: .userDefaults).log("\(firstLaunchMessage)") + MSLogger.make(category: .userDefaults).debug("\(firstLaunchMessage)") + #endif - if self.isFirstLaunch { - self.createNewUser() - } + self.createNewUserWhenFirstLaunch() case .viewNeedsReloaded: let isRecording = self.journeyRepository.fetchIsRecording() self.state.isRecording.send(isRecording) @@ -103,7 +99,7 @@ public final class HomeViewModel { private extension HomeViewModel { - func createNewUser() { + func createNewUserWhenFirstLaunch() { guard self.isFirstLaunch else { return } Task { @@ -125,10 +121,8 @@ private extension HomeViewModel { self.state.isStartButtonLoading.send(true) defer { self.state.isStartButtonLoading.send(false) } - let userID = try self.userRepository.fetchUUID() - #if DEBUG - MSLogger.make(category: .home).debug("유저 ID 조회 성공: \(userID)") - #endif + guard let userID = self.userRepository.fetchUUID() else { return } + let result = await self.journeyRepository.startJourney(at: coordinate, userID: userID) switch result { case .success(let recordingJourney): @@ -141,7 +135,7 @@ private extension HomeViewModel { } func fetchJourneys(minCoordinate: Coordinate, maxCoordinate: Coordinate) { - guard let userID = try? self.userRepository.fetchUUID() else { return } + guard let userID = self.userRepository.fetchUUID() else { return } Task { let result = await self.journeyRepository.fetchJourneyList(userID: userID, diff --git a/iOS/Features/Home/Sources/NavigateMap/Presentation/Common/MapViewController.swift b/iOS/Features/Home/Sources/NavigateMap/Presentation/Common/MapViewController.swift index a6c6b0f..ccdb759 100644 --- a/iOS/Features/Home/Sources/NavigateMap/Presentation/Common/MapViewController.swift +++ b/iOS/Features/Home/Sources/NavigateMap/Presentation/Common/MapViewController.swift @@ -313,7 +313,9 @@ extension MapViewController: CLLocationManagerDelegate { let coordinate2D = CLLocationCoordinate2D(latitude: newCurrentLocation.coordinate.latitude, longitude: newCurrentLocation.coordinate.longitude) + recordJourneyViewModel.trigger(.locationDidUpdated(coordinate2D)) + recordJourneyViewModel.trigger(.locationsShouldRecorded([coordinate2D])) } private func handleAuthorizationChange(_ manager: CLLocationManager) { diff --git a/iOS/Features/Home/Sources/NavigateMap/Presentation/RecordJourney/RecordJourneyViewModel.swift b/iOS/Features/Home/Sources/NavigateMap/Presentation/RecordJourney/RecordJourneyViewModel.swift index 54d5ebc..1d4e0f7 100644 --- a/iOS/Features/Home/Sources/NavigateMap/Presentation/RecordJourney/RecordJourneyViewModel.swift +++ b/iOS/Features/Home/Sources/NavigateMap/Presentation/RecordJourney/RecordJourneyViewModel.swift @@ -73,7 +73,8 @@ public final class RecordJourneyViewModel: MapViewModel { } case .recordingDidCancelled: Task { - let userID = try self.userRepository.fetchUUID() + guard let userID = self.userRepository.fetchUUID() else { return } + let recordingJourney = self.state.recordingJourney.value let result = await self.journeyRepository.deleteJourney(recordingJourney, userID: userID) switch result { diff --git a/iOS/Features/JourneyList/Sources/JourneyList/Presentation/VIew/MSCollectionView.swift b/iOS/Features/JourneyList/Sources/JourneyList/Presentation/VIew/MSCollectionView.swift index f3dbe88..20b5798 100644 --- a/iOS/Features/JourneyList/Sources/JourneyList/Presentation/VIew/MSCollectionView.swift +++ b/iOS/Features/JourneyList/Sources/JourneyList/Presentation/VIew/MSCollectionView.swift @@ -11,9 +11,12 @@ final class MSCollectionView: UICollectionView { override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? { // Cell + let headers = self.visibleSupplementaryViews(ofKind: UICollectionView.elementKindSectionHeader) let cells = self.visibleCells for cell in cells where cell.frame.contains(point) { - return super.hitTest(point, with: event) + for header in headers where !header.frame.contains(point) { + return super.hitTest(point, with: event) + } } return nil diff --git a/iOS/MSCoreKit/Sources/MSKeychainStorage/MSKeychainStorage.swift b/iOS/MSCoreKit/Sources/MSKeychainStorage/MSKeychainStorage.swift index 70eda35..619c1fb 100644 --- a/iOS/MSCoreKit/Sources/MSKeychainStorage/MSKeychainStorage.swift +++ b/iOS/MSCoreKit/Sources/MSKeychainStorage/MSKeychainStorage.swift @@ -68,7 +68,7 @@ public struct MSKeychainStorage { /// Keychain에 저장된 모든 데이터를 삭제합니다. public func deleteAll() throws { - for account in Accounts.allCases { + for account in Accounts.allCases where try self.exists(account: account.rawValue) { try self.delete(account: account.rawValue) } } diff --git a/iOS/MSData/Sources/MSData/DTO/Response/Journey/RecordSpotResponseDTO.swift b/iOS/MSData/Sources/MSData/DTO/Response/Journey/RecordJourneyResponseDTO.swift similarity index 77% rename from iOS/MSData/Sources/MSData/DTO/Response/Journey/RecordSpotResponseDTO.swift rename to iOS/MSData/Sources/MSData/DTO/Response/Journey/RecordJourneyResponseDTO.swift index 359b2a4..00de500 100644 --- a/iOS/MSData/Sources/MSData/DTO/Response/Journey/RecordSpotResponseDTO.swift +++ b/iOS/MSData/Sources/MSData/DTO/Response/Journey/RecordJourneyResponseDTO.swift @@ -1,5 +1,5 @@ // -// RecordSpotResponseDTO.swift +// RecordJourneyResponseDTO.swift // MSData // // Created by 이창준 on 2023.12.06. @@ -7,7 +7,7 @@ import Foundation -public struct RecordSpotResponseDTO: Decodable { +public struct RecordJourneyResponseDTO: Decodable { // MARK: - Properties diff --git a/iOS/MSData/Sources/MSData/Repository/JourneyRepository.swift b/iOS/MSData/Sources/MSData/Repository/JourneyRepository.swift index 9d9d604..9d6b389 100644 --- a/iOS/MSData/Sources/MSData/Repository/JourneyRepository.swift +++ b/iOS/MSData/Sources/MSData/Repository/JourneyRepository.swift @@ -156,11 +156,11 @@ public struct JourneyRepositoryImplementation: JourneyRepository { let coordinatesDTO = coordinates.map { CoordinateDTO($0) } let requestDTO = RecordCoordinateRequestDTO(journeyID: journeyID, coordinates: coordinatesDTO) let router = JourneyRouter.recordCoordinate(dto: requestDTO) - let result = await self.networking.request(RecordCoordinateRequestDTO.self, router: router) + let result = await self.networking.request(RecordJourneyResponseDTO.self, router: router) switch result { case .success(let responseDTO): let coordinates = responseDTO.coordinates.map { $0.toDomain() } - let recordingJourney = RecordingJourney(id: responseDTO.journeyID, + let recordingJourney = RecordingJourney(id: journeyID, startTimestamp: Date(), spots: [], coordinates: coordinates) diff --git a/iOS/MSData/Sources/MSData/Repository/UserRepository.swift b/iOS/MSData/Sources/MSData/Repository/UserRepository.swift index eea4802..cb7d6fc 100644 --- a/iOS/MSData/Sources/MSData/Repository/UserRepository.swift +++ b/iOS/MSData/Sources/MSData/Repository/UserRepository.swift @@ -8,12 +8,13 @@ import Foundation import MSKeychainStorage +import MSLogger import MSNetworking public protocol UserRepository { func createUser() async -> Result - func fetchUUID() throws -> UUID + func fetchUUID() -> UUID? } @@ -35,8 +36,12 @@ public struct UserRepositoryImplementation: UserRepository { // MARK: - Functions public func createUser() async -> Result { - guard let userID = try? self.fetchUUID() else { - return .failure(MSKeychainStorage.KeychainError.transactionError) + // Keychain에 UserID가 저장되어 있는 지 확인하고 아니라면 새로 생성 + let userID: UUID + if let existingUserID = self.fetchUUID() { + userID = existingUserID + } else { + userID = UUID() } let requestDTO = UserRequestDTO(userID: userID) @@ -52,16 +57,17 @@ public struct UserRepositoryImplementation: UserRepository { } /// UUID가 이미 키체인에 등록되어 있다면 가져옵니다. - /// 그렇지 않다면 새로 생성하고, 키체인에 등록합니다. - public func fetchUUID() throws -> UUID { + public func fetchUUID() -> UUID? { let account = MSKeychainStorage.Accounts.userID.rawValue - if let userID = try? self.keychain.get(UUID.self, account: account) { - return userID + guard let userID = try? self.keychain.get(UUID.self, account: account) else { + MSLogger.make(category: .keychain).error("Keychain에서 UserID를 조회하는 것에 실패했습니다.") + return nil } - let newUserID = UUID() - try self.keychain.set(value: newUserID, account: account) - return newUserID + #if DEBUG + MSLogger.make(category: .keychain).debug("Keychain에서 UserID를 조회했습니다: \(userID)") + #endif + return userID } } diff --git a/iOS/MusicSpot/MusicSpot/SceneDelegate.swift b/iOS/MusicSpot/MusicSpot/SceneDelegate.swift index 42e8d6d..748633e 100644 --- a/iOS/MusicSpot/MusicSpot/SceneDelegate.swift +++ b/iOS/MusicSpot/MusicSpot/SceneDelegate.swift @@ -8,6 +8,7 @@ import UIKit import JourneyList +import MSConstants import MSData import MSDesignSystem @@ -18,6 +19,14 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate { var window: UIWindow? private var appCoordinator: Coordinator! + #if DEBUG + @UserDefaultsWrapped(UserDefaultsKey.recordingJourneyID, defaultValue: nil) + var recordingJourneyID: String? + @UserDefaultsWrapped(UserDefaultsKey.isFirstLaunch, defaultValue: false) + var isFirstLaunch: Bool + var keychain = MSKeychainStorage() + #endif + // MARK: - Functions func scene(_ scene: UIScene, @@ -51,3 +60,28 @@ private extension SceneDelegate { } } + + +// MARK: - Debug + +#if DEBUG + +import MSKeychainStorage +import MSLogger +import MSUserDefaults + +private extension SceneDelegate { + + func prepareToDebug() { + self.isFirstLaunch = true + self.recordingJourneyID = nil + do { + try self.keychain.deleteAll() + } catch { + MSLogger.make(category: .keychain).error("키체인 초기화 실패") + } + } + +} + +#endif