Skip to content

Commit 2e781b3

Browse files
authored
Merge pull request #339 from EAT-SSU/fix/#335
[#335] ์ง€๋„ ๋งˆ์ปค ํด๋Ÿฌ์Šคํ„ฐ๋ง ๋„์ž…
2 parents d99007a + 5d3383e commit 2e781b3

File tree

25 files changed

+901
-251
lines changed

25 files changed

+901
-251
lines changed
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
//
2+
// AuthenticationManager.swift
3+
// EATSSU
4+
//
5+
// Created by ํ™ฉ์ƒํ™˜ on 10/12/25.
6+
//
7+
8+
import Foundation
9+
import RealmSwift
10+
11+
enum AuthResult {
12+
case authenticated
13+
case notAuthenticated
14+
case sessionExpired
15+
16+
var errorMessage: String? {
17+
if case .sessionExpired = self {
18+
return "์„ธ์…˜์ด ๋งŒ๋ฃŒ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ๋‹ค์‹œ ๋กœ๊ทธ์ธํ•ด์ฃผ์„ธ์š”."
19+
}
20+
return nil
21+
}
22+
}
23+
24+
final class AuthenticationManager {
25+
static let shared = AuthenticationManager()
26+
private init() {}
27+
28+
/// ์ €์žฅ๋œ ํ† ํฐ์„ ํ™•์ธํ•˜๊ณ  ํ•„์š”์‹œ ๊ฐฑ์‹ ํ•˜์—ฌ ์ธ์ฆ ์ƒํƒœ๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.
29+
func checkAuthentication() async -> AuthResult {
30+
// 1. ํ† ํฐ์ด ์—†์œผ๋ฉด ๋ฏธ์ธ์ฆ ์ƒํƒœ
31+
guard hasStoredToken() else {
32+
return .notAuthenticated
33+
}
34+
35+
// 2. ํ† ํฐ์ด ์žˆ์œผ๋ฉด ๊ฐฑ์‹  ์‹œ๋„
36+
do {
37+
try await TokenManager.shared.refreshIfNeededWithThrow()
38+
return .authenticated
39+
} catch {
40+
// 3. ๊ฐฑ์‹  ์‹คํŒจํ•˜๋ฉด ํ† ํฐ ์‚ญ์ œ ํ›„ ์„ธ์…˜ ๋งŒ๋ฃŒ ์ฒ˜๋ฆฌ
41+
RealmService.shared.deleteAll(Token.self)
42+
return .sessionExpired
43+
}
44+
}
45+
46+
private func hasStoredToken() -> Bool {
47+
!RealmService.shared.getToken().isEmpty
48+
}
49+
}

โ€ŽEATSSU/App/Sources/Data/Network/Foundation/TokenManager.swiftโ€Ž

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,13 @@ final class TokenManager {
5555
guard let data = Data(base64Encoded: base64) else { return nil }
5656
return try? JSONDecoder().decode(TokenPayload.self, from: data)
5757
}
58+
59+
/// ์—๋Ÿฌ๋ฅผ ์ƒ์œ„๋กœ ์ „ํŒŒํ•˜๋Š” ๋ฒ„์ „
60+
func refreshIfNeededWithThrow() async throws {
61+
if isTokenExpiringSoon() {
62+
try await TokenRefresher.shared.refreshIfNeeded()
63+
}
64+
}
5865
}
5966

6067
extension TokenManager {

โ€ŽEATSSU/App/Sources/Presentation/Auth/ViewController/LoginViewController.swiftโ€Ž

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@ final class LoginViewController: BaseViewController {
3030

3131
override func viewWillAppear(_ animated: Bool) {
3232
super.viewWillAppear(animated)
33-
handleAutoLogin()
3433
}
3534

3635
override func viewDidLoad() {
@@ -79,15 +78,6 @@ final class LoginViewController: BaseViewController {
7978
FirebaseRemoteConfig.shared.fetchIsVacationPeriod()
8079
}
8180

82-
/// Realm์— ์ €์žฅ๋œ ํ† ํฐ์ด ์žˆ๋Š”์ง€ ํ™•์ธ ํ›„, ์žˆ์œผ๋ฉด ํ™ˆ ํ™”๋ฉด์œผ๋กœ ์ด๋™ํ•œ๋‹ค.
83-
private func handleAutoLogin() {
84-
guard hasStoredToken() else { return }
85-
#if DEBUG
86-
print("์ €์žฅ๋œ AccessToken: ", RealmService.shared.getToken())
87-
#endif
88-
changeIntoHomeViewController()
89-
}
90-
9181
private func hasStoredToken() -> Bool {
9282
!RealmService.shared.getToken().isEmpty
9383
}

โ€ŽEATSSU/App/Sources/Presentation/Home/ViewController/HomeRestaurantViewController.swiftโ€Ž

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -75,29 +75,24 @@ final class HomeRestaurantViewController: BaseViewController {
7575
// ๋ณ€๊ฒฝ ๋ฉ”๋‰ด ๋ฐ์ดํ„ฐ (์‹๋‹น๋ช…: ๋ฉ”๋‰ด ๋ฐฐ์—ด)
7676
var changeMenuTableViewData: [String: [ChangeMenuTableResponse]] = [:] {
7777
didSet {
78-
// ๋ฉ”๋‰ด ์ด๋ฆ„์ด ๋นˆ ๊ฐ’์ด ์•„๋‹Œ ๋ฐ์ดํ„ฐ๋งŒ ํ•„ํ„ฐ๋ง
79-
changeMenuTableViewData = changeMenuTableViewData.mapValues { menuTableResponses in
80-
menuTableResponses.filter { response in
81-
!(response.briefMenus.first?.name.isEmpty ?? true)
82-
}
83-
}
84-
85-
// ํ˜„์žฌ ์„น์…˜๋งŒ reload
86-
if let sectionIndex = getSectionIndex(for: currentRestaurant) {
87-
restaurantView.restaurantTableView.reloadSections([sectionIndex], with: .automatic)
78+
DispatchQueue.main.async { [weak self] in
79+
guard let self = self,
80+
let sectionIndex = self.getSectionIndex(for: self.currentRestaurant) else { return }
81+
self.restaurantView.restaurantTableView.reloadSections([sectionIndex], with: .automatic)
8882
}
8983
}
9084
}
9185

9286
// ๊ณ ์ • ๋ฉ”๋‰ด ๋ฐ์ดํ„ฐ (๊ฐ„์‹์ฝ”๋„ˆ)
9387
var fixMenuTableViewData: [String: [Menus]] = [:] {
9488
didSet {
95-
if let sectionIndex = getSectionIndex(for: currentRestaurant) {
96-
restaurantView.restaurantTableView.reloadSections([sectionIndex], with: .automatic)
89+
DispatchQueue.main.async { [weak self] in
90+
guard let self = self,
91+
let sectionIndex = self.getSectionIndex(for: self.currentRestaurant) else { return }
92+
self.restaurantView.restaurantTableView.reloadSections([sectionIndex], with: .automatic)
9793
}
9894
}
9995
}
100-
10196
// ๋ฉ”๋‰ด API ์š”์ฒญ์„ ์œ„ํ•œ Moya Provider
10297
let menuProvider = MoyaProvider<HomeRouter>(plugins: [ESMoyaLoggingPlugin()])
10398

@@ -377,7 +372,13 @@ extension HomeRestaurantViewController {
377372
do {
378373
self.currentRestaurant = restaurant
379374
let responseDetailDto = try responseData.map(BaseResponse<[ChangeMenuTableResponse]>.self)
380-
self.changeMenuTableViewData[restaurant] = responseDetailDto.result
375+
376+
let filteredMenus = responseDetailDto.result?.filter {
377+
!($0.briefMenus.first?.name.isEmpty ?? true)
378+
}
379+
380+
self.changeMenuTableViewData[restaurant] = filteredMenus
381+
381382
} catch let err {
382383
print(err.localizedDescription)
383384
}
Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
//
2+
// MainMapViewController+Location.swift
3+
// EATSSU
4+
//
5+
// Created by ํ™ฉ์ƒํ™˜ on 10/4/25.
6+
//
7+
8+
import UIKit
9+
import CoreLocation
10+
11+
// MARK: - Location Management
12+
13+
extension MainMapViewController: CLLocationManagerDelegate {
14+
15+
func setupLocationButtonObserver() {
16+
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) { [weak self] in
17+
guard let self = self else { return }
18+
19+
if let locationButton = self.findLocationButton(in: self.root.mapView) {
20+
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(self.locationButtonTapped))
21+
tapGesture.delegate = self
22+
locationButton.addGestureRecognizer(tapGesture)
23+
}
24+
}
25+
}
26+
27+
@objc func locationButtonTapped() {
28+
let status = locationManager.authorizationStatus
29+
30+
switch status {
31+
case .notDetermined:
32+
hasRequestedLocationPermission = true
33+
locationManager.requestWhenInUseAuthorization()
34+
35+
case .denied, .restricted:
36+
showLocationPermissionAlert()
37+
38+
case .authorizedWhenInUse, .authorizedAlways:
39+
break
40+
41+
@unknown default:
42+
break
43+
}
44+
}
45+
46+
func findLocationButton(in view: UIView) -> UIView? {
47+
for subview in view.subviews {
48+
if String(describing: type(of: subview)).contains("LocationButton") {
49+
return subview
50+
}
51+
if let found = findLocationButton(in: subview) {
52+
return found
53+
}
54+
}
55+
return nil
56+
}
57+
58+
func locationManagerDidChangeAuthorization(_ manager: CLLocationManager) {
59+
switch manager.authorizationStatus {
60+
case .authorizedWhenInUse, .authorizedAlways:
61+
root.mapView.mapView.positionMode = .direction
62+
63+
case .denied, .restricted:
64+
if hasRequestedLocationPermission {
65+
showLocationPermissionAlert()
66+
hasRequestedLocationPermission = false
67+
}
68+
69+
case .notDetermined:
70+
break
71+
72+
@unknown default:
73+
break
74+
}
75+
}
76+
77+
func showLocationPermissionAlert() {
78+
let alert = UIAlertController(
79+
title: "์œ„์น˜ ๊ถŒํ•œ ํ•„์š”",
80+
message: "์ง€๋„์—์„œ ๋‚ด ์œ„์น˜๋ฅผ ๋ฐ”๋กœ ํ™•์ธํ•˜๊ณ , ํ˜„์žฌ ์œ„์น˜ ์ฃผ๋ณ€์˜ ์ œํœด์ ๋“ค์„ ์†์‰ฝ๊ฒŒ ์ฐพ์•„๋ณผ ์ˆ˜ ์žˆ๋„๋ก ์œ„์น˜ ๊ถŒํ•œ์„ ํ—ˆ์šฉํ•ด ์ฃผ์„ธ์š”.",
81+
preferredStyle: .alert
82+
)
83+
84+
let settingsAction = UIAlertAction(title: "์„ค์ •์œผ๋กœ ์ด๋™", style: .default) { _ in
85+
if let settingsURL = URL(string: UIApplication.openSettingsURLString) {
86+
UIApplication.shared.open(settingsURL)
87+
}
88+
}
89+
90+
let cancelAction = UIAlertAction(title: "์ทจ์†Œ", style: .cancel)
91+
92+
alert.addAction(settingsAction)
93+
alert.addAction(cancelAction)
94+
95+
present(alert, animated: true)
96+
}
97+
98+
func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
99+
if let clError = error as? CLError {
100+
switch clError.code {
101+
case .denied:
102+
if hasRequestedLocationPermission {
103+
showLocationPermissionAlert()
104+
hasRequestedLocationPermission = false
105+
}
106+
default:
107+
break
108+
}
109+
}
110+
}
111+
}
112+
113+
// MARK: - UIGestureRecognizerDelegate
114+
115+
extension MainMapViewController: UIGestureRecognizerDelegate {
116+
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
117+
return true
118+
}
119+
}

0 commit comments

Comments
ย (0)