From 2408efce447ce5df99d556531389541e80bf8940 Mon Sep 17 00:00:00 2001 From: JaeWoong Eum Date: Wed, 11 Mar 2026 22:11:52 +0900 Subject: [PATCH 1/7] =?UTF-8?q?[BUGFIX]=20=EC=95=8C=EB=9E=8C=20=EC=A2=85?= =?UTF-8?q?=EB=A3=8C=20=EC=8B=9C=20=ED=98=84=20=EC=9C=84=EC=B9=98=201?= =?UTF-8?q?=ED=9A=8C=20=EA=B0=80=EC=A7=80=EA=B3=A0=20=EC=98=A4=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Atcha-iOS/Presentation/Location/MainViewController.swift | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/Atcha-iOS/Presentation/Location/MainViewController.swift b/Atcha-iOS/Presentation/Location/MainViewController.swift index 81f5265..9849b79 100644 --- a/Atcha-iOS/Presentation/Location/MainViewController.swift +++ b/Atcha-iOS/Presentation/Location/MainViewController.swift @@ -509,9 +509,14 @@ extension MainViewController { mapContainerView.clearMapView() mapContainerView.beforeUserMarker() - if let coord = viewModel.selectedLocation ?? viewModel.currentLocation { - mapContainerView.setupCenter(location: coord) + if let currentCoord = viewModel.currentLocation { + // 현재 좌표가 있다면 즉시 이동 + mapContainerView.setupCenter(location: currentCoord) + viewModel.selectedLocation = currentCoord // 주소 검색 결과도 현위치로 갱신 + shouldCenterToCurrentLocationOnce = false } else { + // 아직 좌표가 없다면, 다음 위치 업데이트 시점에 이동하도록 예약 + shouldCenterToCurrentLocationOnce = true viewModel.setupLocation() } From 2ee0eda2b9a1214255dff2cba217606b50825ca6 Mon Sep 17 00:00:00 2001 From: JaeWoong Eum Date: Wed, 11 Mar 2026 22:37:45 +0900 Subject: [PATCH 2/7] =?UTF-8?q?[BUGFIX]=202=EB=B6=84=20=EC=9E=90=EB=8F=99?= =?UTF-8?q?=20=ED=83=80=EC=9E=84=EC=95=84=EC=9B=83=20=EC=A4=91=EB=B3=B5=20?= =?UTF-8?q?=EC=A0=81=EC=9A=A9=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Atcha-iOS/Core/Manager/AlarmManager.swift | 3 +++ Atcha-iOS/Presentation/Lock/LockViewController.swift | 1 + 2 files changed, 4 insertions(+) diff --git a/Atcha-iOS/Core/Manager/AlarmManager.swift b/Atcha-iOS/Core/Manager/AlarmManager.swift index 2a2fa3b..765aab0 100644 --- a/Atcha-iOS/Core/Manager/AlarmManager.swift +++ b/Atcha-iOS/Core/Manager/AlarmManager.swift @@ -102,6 +102,9 @@ final class AlarmManager { /// 완전 정지: 예약/타이머/진동/알림/오디오 모두 끊기 func stopAlarm(keepSilent: Bool = false) { + autoStopWorkItem?.cancel() + autoStopWorkItem = nil + shouldKeepBackgroundAudio = false pendingStartWorkItem?.cancel() pendingStartWorkItem = nil diff --git a/Atcha-iOS/Presentation/Lock/LockViewController.swift b/Atcha-iOS/Presentation/Lock/LockViewController.swift index 14bcac8..e78ccaa 100644 --- a/Atcha-iOS/Presentation/Lock/LockViewController.swift +++ b/Atcha-iOS/Presentation/Lock/LockViewController.swift @@ -142,6 +142,7 @@ final class LockViewController: BaseViewController { @objc private func startTapped() { viewModel.cancelLockScreenTimer() AlarmManager.shared.stopAlarm() + AlarmManager.shared.removeAllAlarmNotificationsExceptAutoStop() let wrapper = UserDefaultsWrapper.shared let legInfo = wrapper.object(forKey: UserDefaultsWrapper.Key.legInfo.rawValue, of: LegInfo.self) From 32d020abb9a7f334e2a327e2533f5e5d6793bb50 Mon Sep 17 00:00:00 2001 From: JaeWoong Eum Date: Wed, 11 Mar 2026 22:51:45 +0900 Subject: [PATCH 3/7] =?UTF-8?q?[BUGFIX]=20=EC=A7=91=EC=A3=BC=EC=86=8C=20?= =?UTF-8?q?=EB=A1=9C=EC=A7=81=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../HomeRegister/HomeRegisterViewModel.swift | 39 +++++++++++-------- 1 file changed, 23 insertions(+), 16 deletions(-) diff --git a/Atcha-iOS/Presentation/Onboarding/HomeRegister/HomeRegisterViewModel.swift b/Atcha-iOS/Presentation/Onboarding/HomeRegister/HomeRegisterViewModel.swift index 5f3e0eb..4ae976a 100644 --- a/Atcha-iOS/Presentation/Onboarding/HomeRegister/HomeRegisterViewModel.swift +++ b/Atcha-iOS/Presentation/Onboarding/HomeRegister/HomeRegisterViewModel.swift @@ -51,28 +51,35 @@ final class HomeRegisterViewModel: BaseViewModel { private func setupInitialState() { let defaults = UserDefaultsWrapper.shared + // 1. 이름과 주소가 이미 있다면 (직접 등록했던 유저) 바로 표시 if let buildingName = defaults.string(forKey: UserDefaultsWrapper.Key.buildingName.rawValue), let address = defaults.string(forKey: UserDefaultsWrapper.Key.homeAddress.rawValue) { self.selectedState = .selected(name: buildingName, address: address) - } else { - if let lat = defaults.double(forKey: UserDefaultsWrapper.Key.homeLat.rawValue), - let lon = defaults.double(forKey: UserDefaultsWrapper.Key.homeLon.rawValue) { - Task { - if let location = try? await fetchCurrentAddress(lat: lat, lon: lon) { - let name = location.name ?? "" - let address = location.address ?? "" - - defaults.set(name, forKey: UserDefaultsWrapper.Key.buildingName.rawValue) - defaults.set(address, forKey: UserDefaultsWrapper.Key.homeAddress.rawValue) - - await MainActor.run { - self.selectedState = .selected(name: name, address: address) - } + return + } + + // 2. 이름은 없지만 좌표는 있다면 (방금 로그인한 유저) + let lat = defaults.double(forKey: UserDefaultsWrapper.Key.homeLat.rawValue) + let lon = defaults.double(forKey: UserDefaultsWrapper.Key.homeLon.rawValue) + + if let lat, let lon, lat != 0.0 && lon != 0.0 { + // 이름이 없으니 좌표로 이름을 새로 따와서 채워주기 + Task { + if let location = try? await fetchCurrentAddress(lat: lat, lon: lon) { + let name = location.name ?? "" + let addr = location.address ?? "" + + // 따온 이름을 저장해두기 (다음엔 1번 조건에서 걸리도록) + defaults.set(name, forKey: UserDefaultsWrapper.Key.buildingName.rawValue) + defaults.set(addr, forKey: UserDefaultsWrapper.Key.homeAddress.rawValue) + + await MainActor.run { + self.selectedState = .selected(name: name, address: addr) } } - } else { - self.selectedState = LocationSelectionState.none } + } else { + self.selectedState = LocationSelectionState.none } } From cc82bcb2954bd6256599b57c5c31bde9872dc387 Mon Sep 17 00:00:00 2001 From: JaeWoong Eum Date: Thu, 12 Mar 2026 00:23:05 +0900 Subject: [PATCH 4/7] =?UTF-8?q?[BUGFIX]=20=EA=B2=80=EC=83=89=20=EC=A2=8C?= =?UTF-8?q?=ED=91=9C=20=EB=A1=9C=EC=A7=81=20=EA=B0=9C=EC=84=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../CourseSearch/CourseSearchViewModel.swift | 12 ++++++------ .../Location/MainViewController.swift | 10 +++++----- .../Presentation/Location/MainViewModel.swift | 19 +++++++++++-------- .../Location/View/TMapContainerView.swift | 2 +- 4 files changed, 23 insertions(+), 20 deletions(-) diff --git a/Atcha-iOS/Presentation/Course/CourseSearch/CourseSearchViewModel.swift b/Atcha-iOS/Presentation/Course/CourseSearch/CourseSearchViewModel.swift index 27060bf..0417617 100644 --- a/Atcha-iOS/Presentation/Course/CourseSearch/CourseSearchViewModel.swift +++ b/Atcha-iOS/Presentation/Course/CourseSearch/CourseSearchViewModel.swift @@ -130,12 +130,12 @@ final class CourseSearchViewModel: BaseViewModel { // MARK: - 코스 검색 스트리밍용 func startCourseStream() { - if isBlackoutNow() { - setLoading(false) - isServerError = true - courses = [] - return - } +// if isBlackoutNow() { +// setLoading(false) +// isServerError = true +// courses = [] +// return +// } courseStreamTask?.cancel() setLoading(true) diff --git a/Atcha-iOS/Presentation/Location/MainViewController.swift b/Atcha-iOS/Presentation/Location/MainViewController.swift index 9849b79..8cd9a6f 100644 --- a/Atcha-iOS/Presentation/Location/MainViewController.swift +++ b/Atcha-iOS/Presentation/Location/MainViewController.swift @@ -401,13 +401,13 @@ extension MainViewController { if viewModel.isGuest { presentLoginAlert() } else { - AmplitudeManager.shared.track(.course_search_click) - - guard let startCoord = viewModel.currentLocation else { + guard let startCoord = mapContainerView.tMapWrapper.mapView.getCenter() else { view.showToast(message: "현재 위치를 확인 중이에요. 잠시 후 다시 시도해 주세요.") return } + AmplitudeManager.shared.track(.course_search_click) + let wrapper = UserDefaultsWrapper.shared let endLatStr = wrapper.string(forKey: UserDefaultsWrapper.Key.homeLat.rawValue) ?? "37.554722" let endLonStr = wrapper.string(forKey: UserDefaultsWrapper.Key.homeLon.rawValue) ?? "126.970833" @@ -424,7 +424,7 @@ extension MainViewController { } viewModel.handleRoute(route: .courseSearch( - startLat: "", startLon: "", startAddress: "" + startLat: String(startCoord.latitude), startLon: String(startCoord.longitude), startAddress: "" )) } } @@ -580,7 +580,7 @@ extension MainViewController { .compactMap { $0 } .receive(on: RunLoop.main) .sink { _ in - // 👉 뷰모델에서 알아서 주소를 검색하므로 뷰컨트롤러는 카메라를 건드리지 않음! + // 뷰모델에서 알아서 주소를 검색하므로 뷰컨트롤러는 카메라를 건드리지 않음! } .store(in: &cancellables) } diff --git a/Atcha-iOS/Presentation/Location/MainViewModel.swift b/Atcha-iOS/Presentation/Location/MainViewModel.swift index 15880a2..8146d6e 100644 --- a/Atcha-iOS/Presentation/Location/MainViewModel.swift +++ b/Atcha-iOS/Presentation/Location/MainViewModel.swift @@ -485,15 +485,18 @@ extension MainViewModel { address: lastReverseGeocode?.address, radius: lastReverseGeocode?.radius))) - case .courseSearch: - guard let currentLocation else { return } - let lat: String = "\(currentLocation.latitude)" - let lon: String = "\(currentLocation.longitude)" - let address: String = address ?? "" + case .courseSearch(let startLat, let startLon, _): + + if lastReverseGeocode != nil { + routeHandler?(.courseSearch(startLat: "\(lastReverseGeocode?.lat ?? 0.0)", + startLon: "\(lastReverseGeocode?.lon ?? 0.0)", + startAddress: lastReverseGeocode?.address ?? "")) + } else { + routeHandler?(.courseSearch(startLat: startLat, + startLon: startLon, + startAddress: address ?? "")) + } - routeHandler?(.courseSearch(startLat: lat, - startLon: lon, - startAddress: address)) case .myPage: routeHandler?(.myPage) diff --git a/Atcha-iOS/Presentation/Location/View/TMapContainerView.swift b/Atcha-iOS/Presentation/Location/View/TMapContainerView.swift index 2cb92c3..605b2fe 100644 --- a/Atcha-iOS/Presentation/Location/View/TMapContainerView.swift +++ b/Atcha-iOS/Presentation/Location/View/TMapContainerView.swift @@ -11,7 +11,7 @@ import TMapSDK import SnapKit final class TMapContainerView: UIView { - private var tMapWrapper: TMapWrapper! + var tMapWrapper: TMapWrapper! var gestureTargetView: UIView { tMapWrapper.mapView } var onUserInteraction: (() -> Void)? From f9e17fc23dafec1387ae8dab005373f67c6515c3 Mon Sep 17 00:00:00 2001 From: JaeWoong Eum Date: Thu, 12 Mar 2026 00:40:04 +0900 Subject: [PATCH 5/7] =?UTF-8?q?[BUGFIX]=20=EA=B0=80=EC=9E=A5=20=EB=8A=A6?= =?UTF-8?q?=EC=9D=80=20=EB=A7=89=EC=B0=A8=20=ED=82=A4=EC=9B=8C=EB=93=9C=20?= =?UTF-8?q?=EA=B0=B1=EC=8B=A0=20=EB=A1=9C=EC=A7=81=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../CourseSearchViewController.swift | 41 +++++++++++++++++-- 1 file changed, 38 insertions(+), 3 deletions(-) diff --git a/Atcha-iOS/Presentation/Course/CourseSearch/CourseSearchViewController.swift b/Atcha-iOS/Presentation/Course/CourseSearch/CourseSearchViewController.swift index 1f59d7f..3601699 100644 --- a/Atcha-iOS/Presentation/Course/CourseSearch/CourseSearchViewController.swift +++ b/Atcha-iOS/Presentation/Course/CourseSearch/CourseSearchViewController.swift @@ -65,6 +65,7 @@ final class CourseSearchViewController: BaseViewController Date: Thu, 12 Mar 2026 00:44:09 +0900 Subject: [PATCH 6/7] =?UTF-8?q?[BUGFIX]=20=EC=83=81=EC=84=B8=20=EA=B2=BD?= =?UTF-8?q?=EB=A1=9C=20=ED=99=94=EB=A9=B4=20=EC=A4=91=EB=B3=B5=20push=20?= =?UTF-8?q?=EB=B0=A9=EC=A7=80=20=EB=A1=9C=EC=A7=81=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../CourseSearchViewController.swift | 10 -------- .../CourseSearch/CourseSearchViewModel.swift | 12 +++++----- .../Presentation/Location/MainViewModel.swift | 23 ------------------- .../Presentation/Main/MainCoordinator.swift | 6 ++++- 4 files changed, 11 insertions(+), 40 deletions(-) diff --git a/Atcha-iOS/Presentation/Course/CourseSearch/CourseSearchViewController.swift b/Atcha-iOS/Presentation/Course/CourseSearch/CourseSearchViewController.swift index 3601699..4ce2ca0 100644 --- a/Atcha-iOS/Presentation/Course/CourseSearch/CourseSearchViewController.swift +++ b/Atcha-iOS/Presentation/Course/CourseSearch/CourseSearchViewController.swift @@ -284,16 +284,6 @@ final class CourseSearchViewController: BaseViewController Date: Thu, 12 Mar 2026 00:58:35 +0900 Subject: [PATCH 7/7] =?UTF-8?q?[SETTING]=20=EB=B9=8C=EB=93=9C=20=EB=B2=88?= =?UTF-8?q?=ED=98=B8=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Atcha-iOS.xcodeproj/project.pbxproj | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Atcha-iOS.xcodeproj/project.pbxproj b/Atcha-iOS.xcodeproj/project.pbxproj index 2e92916..d83766f 100644 --- a/Atcha-iOS.xcodeproj/project.pbxproj +++ b/Atcha-iOS.xcodeproj/project.pbxproj @@ -2468,7 +2468,7 @@ CODE_SIGN_IDENTITY = "Apple Development"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution"; CODE_SIGN_STYLE = Manual; - CURRENT_PROJECT_VERSION = 15; + CURRENT_PROJECT_VERSION = 1; DEVELOPMENT_TEAM = ""; "DEVELOPMENT_TEAM[sdk=iphoneos*]" = 23SCTLK482; FRAMEWORK_SEARCH_PATHS = ( @@ -2491,7 +2491,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 1.7; + MARKETING_VERSION = 1.8; PRODUCT_BUNDLE_IDENTIFIER = com.atcha.iOS; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; @@ -2515,7 +2515,7 @@ CODE_SIGN_ENTITLEMENTS = "Atcha-iOS/Atcha-iOS.entitlements"; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 15; + CURRENT_PROJECT_VERSION = 1; DEVELOPMENT_TEAM = 23SCTLK482; EXCLUDED_ARCHS = ""; FRAMEWORK_SEARCH_PATHS = ( @@ -2538,7 +2538,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 1.7; + MARKETING_VERSION = 1.8; OTHER_SWIFT_FLAGS = ""; PRODUCT_BUNDLE_IDENTIFIER = com.atcha.iOS; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -2563,7 +2563,7 @@ CODE_SIGN_IDENTITY = "Apple Development"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution"; CODE_SIGN_STYLE = Manual; - CURRENT_PROJECT_VERSION = 15; + CURRENT_PROJECT_VERSION = 1; DEVELOPMENT_TEAM = ""; "DEVELOPMENT_TEAM[sdk=iphoneos*]" = 23SCTLK482; FRAMEWORK_SEARCH_PATHS = ( @@ -2586,7 +2586,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 1.7; + MARKETING_VERSION = 1.8; PRODUCT_BUNDLE_IDENTIFIER = com.atcha.iOS; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = "";