diff --git a/AcaMate.xcodeproj/project.xcworkspace/xcuserdata/seankim.xcuserdatad/UserInterfaceState.xcuserstate b/AcaMate.xcodeproj/project.xcworkspace/xcuserdata/seankim.xcuserdatad/UserInterfaceState.xcuserstate index bcea3c4..8165c44 100644 Binary files a/AcaMate.xcodeproj/project.xcworkspace/xcuserdata/seankim.xcuserdatad/UserInterfaceState.xcuserstate and b/AcaMate.xcodeproj/project.xcworkspace/xcuserdata/seankim.xcuserdatad/UserInterfaceState.xcuserstate differ diff --git a/AcaMate/1. View/0. Common/NavigationView.swift b/AcaMate/1. View/0. Common/NavigationView.swift index 610011f..9024bc6 100644 --- a/AcaMate/1. View/0. Common/NavigationView.swift +++ b/AcaMate/1. View/0. Common/NavigationView.swift @@ -46,6 +46,9 @@ struct NavigationView: View { printLog("\(old.path) => \(new.path)") showHistory() } + .fullView(.Normal.normal) + .setAlert() + .setNetwork() } private func addHistory(path: PathName) { diff --git a/AcaMate/1. View/1. Intro & Login/IntroView.swift b/AcaMate/1. View/1. Intro & Login/IntroView.swift index 3ae437c..4d21e43 100644 --- a/AcaMate/1. View/1. Intro & Login/IntroView.swift +++ b/AcaMate/1. View/1. Intro & Login/IntroView.swift @@ -9,6 +9,7 @@ import SwiftUI import Combine struct IntroView: View { + @EnvironmentObject var alertController: AlertController @State var cancellables: Set = [] @Binding var naviState : NaviState @@ -37,9 +38,10 @@ struct IntroView: View { .foregroundStyle(Color(.Text.detail)) .padding(.bottom,50) } - .fullView(.Normal.normal) + .onAppear { printLog("IntroView_onAppear") + subscribeAlertAction() loadVersion() .sink { completion in switch completion { @@ -48,24 +50,20 @@ struct IntroView: View { case .finished: break } } receiveValue: { version in - switch compareVersion(version.force_ver, currentVersion()){ - case .bigger: - printLog("강제 업데이트") - default: - switch compareVersion(version.final_ver, currentVersion()) { - case .bigger: - if version.choice_update_yn { - printLog("선택 업데이트") - } - else { - printLog("정상 동작") - naviState.set(act: .RESET, path: .Login) - } - default: - printLog("선택 업데이트 넘어감") - naviState.set(act: .MOVE, path: .Login) - - } + let compareForce = compareVersion(version.force_ver, currentVersion()) + let compareChoice = compareVersion(version.final_ver, currentVersion()) + if compareForce == .bigger { + alertController.alertData = SetAlertData().setForceUpdate( + action: alertController.alertAction + ) + alertController.showAlert.toggle() + } else if compareChoice == .bigger && version.choice_update_yn { + alertController.alertData = SetAlertData().setSelectUpdate( + action: alertController.alertAction + ) + alertController.showAlert.toggle() + } else { + naviState.set(act: .RESET, path: .Login) } } .store(in: &cancellables) @@ -74,6 +72,19 @@ struct IntroView: View { } } + private func subscribeAlertAction() { + alertController.alertAction + .compactMap { $0 } + .sink { action in + if action == "updateNow" { + exit(1) + //MARK: - TODO (앱스토어 이동 로직 넣을 것) + } else { + naviState.set(act: .RESET, path: .Login) + } + }.store(in: &cancellables) + } + private func loadVersion() -> Future { return Future { promise in diff --git a/AcaMate/1. View/1. Intro & Login/LoginView.swift b/AcaMate/1. View/1. Intro & Login/LoginView.swift index 02758fd..96535fa 100644 --- a/AcaMate/1. View/1. Intro & Login/LoginView.swift +++ b/AcaMate/1. View/1. Intro & Login/LoginView.swift @@ -8,6 +8,7 @@ import SwiftUI struct LoginView: View { + @EnvironmentObject var alertController: AlertController @Binding var naviState : NaviState var body: some View { @@ -37,7 +38,10 @@ struct LoginView: View { } Button { - naviState.set(act: .MOVE,path: .Intro) + alertController.alertData = SetAlertData().setTest() + alertController.showAlert.toggle() +// naviState.set(act: .MOVE,path: .Intro) + } label: { Text("111111111") } diff --git a/AcaMate/3. Controller/AlertController.swift b/AcaMate/3. Controller/AlertController.swift new file mode 100644 index 0000000..03b2d8f --- /dev/null +++ b/AcaMate/3. Controller/AlertController.swift @@ -0,0 +1,19 @@ +// +// AlertController.swift +// AcaMate +// +// Created by Sean Kim on 12/13/24. +// + +import SwiftUI +import Combine + + +class AlertController: ObservableObject { + @Published var showAlert: Bool = false + var alertData: AlertData = .init(body: "") + + let alertAction = CurrentValueSubject(nil) + + +} diff --git a/AcaMate/4. Model/Alert.swift b/AcaMate/4. Model/Alert.swift index 6c69cc5..6fcba27 100644 --- a/AcaMate/4. Model/Alert.swift +++ b/AcaMate/4. Model/Alert.swift @@ -6,6 +6,7 @@ // import SwiftUI +import Combine struct AlertData { var title: String @@ -24,3 +25,62 @@ struct ButtonType { var role: ButtonRole? var function: (()->())? } + + + +struct SetAlertData { + func setTest() -> AlertData { + return AlertData(title: "TEST", body: "TEST용 알럿 입니다.", + button: [ + ButtonType(name: "테스트", role: .cancel, + function: { + printLog("테스트 중입니다.") + }) + ]) + } + + + /// 강제 업데이트 안내 + func setForceUpdate(action: CurrentValueSubject) -> AlertData { + return AlertData(title: "업데이트 안내", + body: """ + 앱 최신 버전이 나왔습니다. + 앱을 종료 후 업데이트를 해주세요. + """, + button: [ + ButtonType(name: "업데이트 하기", role: .none, + function: { + action.send("updateNow") + }) + ]) + } + + /// 선택 업데이트 안내 + func setSelectUpdate (action: CurrentValueSubject) -> AlertData { + return AlertData(title: "업데이트 안내", + body: """ + 앱 최신 버전이 새로 나왔습니다. + 지금 업데이트 하시겠어요? + """, + button: [ + ButtonType(name: "지금 업데이트", role: .cancel, + function: { + action.send("updateNow") + }), + ButtonType(name: "나중에", role: .none, + function: { + action.send("updateLater") + }), + ]) + } + + /// 네트워크 문제 발생 시 + func setErrorNetwork() -> AlertData { + return AlertData(title: "네트워크 오류", body: "네트워크가 불안정합니다.\n확인 후 다시 시도해주세요.", + button: [ + ButtonType(name: "확인", role: .cancel, function: nil) + ]) + } + +} + diff --git a/AcaMate/5. Modifier/Network.swift b/AcaMate/5. Modifier/Network.swift index 4b776c3..98df925 100644 --- a/AcaMate/5. Modifier/Network.swift +++ b/AcaMate/5. Modifier/Network.swift @@ -10,7 +10,7 @@ import Combine class NetworkMonitor: ObservableObject { static let shared = NetworkMonitor() - + private let monitor = NWPathMonitor() private let queue = DispatchQueue.global(qos: .background) diff --git a/AcaMate/5. Modifier/View.swift b/AcaMate/5. Modifier/View.swift index 285512e..89b8997 100644 --- a/AcaMate/5. Modifier/View.swift +++ b/AcaMate/5. Modifier/View.swift @@ -10,17 +10,41 @@ import Combine struct NetworkModifier: ViewModifier { @ObservedObject private var networkMonitor = NetworkMonitor.shared + @EnvironmentObject var alertController: AlertController func body(content: Content) -> some View { content .onChange(of: networkMonitor.isConnected) { _ , new in - if new { - + if !new { + alertController.alertData = SetAlertData().setErrorNetwork() + alertController.showAlert.toggle() } } } } +struct AlertModifier: ViewModifier { + @EnvironmentObject var controller: AlertController + func body(content: Content) -> some View { + content + .alert(controller.alertData.title, + isPresented: $controller.showAlert, + presenting: $controller.alertData) { data in + let btnCount = data.button.count + ForEach(0 ..< btnCount, id: \.self) { index in + let btn = data.wrappedValue.button[index] + Button(role: btn.role) { + if let function = btn.function { function() } + } label: { + Text("\(btn.name)") + } + } + } message: { data in + Text("\(data.body.wrappedValue)") + } + } +} + extension View { func fullView(_ backColor: Color) -> some View { return self @@ -28,6 +52,13 @@ extension View { .background(backColor) } + func setAlert() -> some View { + self.modifier(AlertModifier()) + } + func setNetwork() -> some View { + self.modifier(NetworkModifier()) + } + func endTextEditing() { UIApplication.shared.sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil) } diff --git a/AcaMate/AcaMateApp.swift b/AcaMate/AcaMateApp.swift index 812e58b..f7adeeb 100644 --- a/AcaMate/AcaMateApp.swift +++ b/AcaMate/AcaMateApp.swift @@ -15,6 +15,7 @@ import KakaoSDKAuth struct AcaMateApp: App { @UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate var cancellables: Set = [] + var alertController = AlertController() init() { printLog("APP INIT") @@ -22,11 +23,13 @@ struct AcaMateApp: App { var body: some Scene { WindowGroup { - NavigationView().onOpenURL { url in - if (AuthApi.isKakaoTalkLoginUrl(url)) { - _ = AuthController.handleOpenUrl(url: url) + NavigationView() + .onOpenURL { url in + if (AuthApi.isKakaoTalkLoginUrl(url)) { + _ = AuthController.handleOpenUrl(url: url) + } } - } + .environmentObject(self.alertController) } } }