[] 네트워크 감지 기능 + 화면 전환 위한 최상단 뷰의 초기 모델 생성

This commit is contained in:
김선규 2024-12-13 02:28:30 +09:00
parent 3e4aa99a18
commit eb726b0c7d
9 changed files with 252 additions and 64 deletions

View File

@ -44,8 +44,8 @@ class AppDelegate: NSObject, UIApplicationDelegate, UNUserNotificationCenterDele
}
center.delegate = self
//MARK: -
// _ = NetworkMonitor.shared
//MARK: -
_ = NetworkMonitor.shared
printLog("End Set AppDelegate")
return true

View File

@ -0,0 +1,84 @@
//
// NavigationView.swift
// AcaMate
//
// Created by Sean Kim on 12/12/24.
//
import SwiftUI
import Combine
struct NavigationView: View {
@State private var naviState : NaviState = .init(act: .NONE, path: .Intro)
@State private var history: [PathName] = [.Intro]
var body: some View {
ZStack {
switch naviState.path {
case .NONE:
EmptyView()
case .Intro:
IntroView(naviState: $naviState)
case .Login :
LoginView(naviState: $naviState)
case .Main:
EmptyView()
}
}
.onChange(of: naviState) { old, new in
switch new.act {
case .NONE:
break
case .ADD:
addHistory(path: new.path)
case .POP:
popHistory()
case .RESET:
resetHistory(path: new.path)
case .MOVE:
moveHistory(path: new.path)
}
// LOG
printLog("\(old.path) => \(new.path)")
showHistory()
}
}
private func addHistory(path: PathName) {
history.append(path)
}
private func popHistory() {
history.removeLast()
naviState.set(act: .NONE, path: history.last ?? .NONE)
}
private func resetHistory(path: PathName) {
history.removeAll()
addHistory(path: path)
}
private func moveHistory(path: PathName) {
if path == .NONE {
naviState.set(act: .RESET, path: history.first ?? .Main)
}
if history.contains(path) {
let remove = history.count - history.firstIndex(of: path)! - 1
history.removeLast(remove)
if remove > 0 {
naviState.set(act: .NONE, path: path)
return
}
}
naviState.set(act: .RESET, path: path)
}
private func showHistory() {
printLog(history)
}
}

View File

@ -10,65 +10,67 @@ import Combine
struct IntroView: View {
@State var cancellables: Set<AnyCancellable> = []
@Binding var naviState : NaviState
var body: some View {
NavigationStack {
VStack(spacing: 0) {
Spacer()
.frame(height: 100)
VStack(spacing: 0) {
Spacer()
.frame(height: 100)
Image("Team_Icon")
.resizable()
.frame(width: 200, height: 200)
.background(.white)
.border(.black)
.padding()
Spacer()
HStack(spacing: 4) {
Image("Team_Icon")
.resizable()
.frame(width: 200, height: 200)
.background(.white)
.border(.black)
.padding()
Spacer()
HStack(spacing: 4) {
Image("Team_Icon")
.resizable()
.frame(width: 24, height: 24)
Text("STEIN")
.font(.nps(font: .bold, size: 16))
.foregroundStyle(Color(.Text.detail))
}
.padding(.bottom,12)
Text("Copyright © Team.Stein")
.font(.nps(font: .regular, size: 14))
.frame(width: 24, height: 24)
Text("STEIN")
.font(.nps(font: .bold, size: 16))
.foregroundStyle(Color(.Text.detail))
.padding(.bottom,50)
}
.fullView(.Normal.normal)
.onAppear {
printLog("IntroView_onAppear")
loadVersion()
.sink { completion in
switch completion {
case .failure(let error):
printLog(error)
case .finished: break
}
} receiveValue: { version in
switch compareVersion(version.force_ver, currentVersion()){
.padding(.bottom,12)
Text("Copyright © Team.Stein")
.font(.nps(font: .regular, size: 14))
.foregroundStyle(Color(.Text.detail))
.padding(.bottom,50)
}
.fullView(.Normal.normal)
.onAppear {
printLog("IntroView_onAppear")
loadVersion()
.sink { completion in
switch completion {
case .failure(let error):
printLog(error)
case .finished: break
}
} receiveValue: { version in
switch compareVersion(version.force_ver, currentVersion()){
case .bigger:
printLog("강제 업데이트")
default:
switch compareVersion(version.final_ver, currentVersion()) {
case .bigger:
printLog("강제 업데이트")
default:
switch compareVersion(version.final_ver, currentVersion()) {
case .bigger:
if version.choice_update_yn {
printLog("선택 업데이트")
}
else {
printLog("정상 동작")
}
default:
printLog("선택 업데이트 넘어감")
if version.choice_update_yn {
printLog("선택 업데이트")
}
else {
printLog("정상 동작")
naviState.set(act: .RESET, path: .Login)
}
default:
printLog("선택 업데이트 넘어감")
naviState.set(act: .MOVE, path: .Login)
}
}
.store(in: &cancellables)
}
}
.store(in: &cancellables)
}
}
@ -101,15 +103,15 @@ struct IntroView: View {
return currentVer
}
private func versionChange(ver: String) -> [Int] {
return ver.components(separatedBy: ["."]).map {Int($0) ?? 0}
}
}
#Preview {
IntroView()
}
//#Preview {
// IntroView(path: $NavigationPath())
//}

View File

@ -8,6 +8,8 @@
import SwiftUI
struct LoginView: View {
@Binding var naviState : NaviState
var body: some View {
VStack(spacing: 0) {
Image("Team_Icon")
@ -34,12 +36,18 @@ struct LoginView: View {
}
}
Button {
naviState.set(act: .MOVE,path: .Intro)
} label: {
Text("111111111")
}
.padding()
}
.fullView(.Normal.normal)
}
}
#Preview {
LoginView()
}
//#Preview {
// LoginView()
//}

View File

@ -0,0 +1,47 @@
//
// Navigation.swift
// AcaMate
//
// Created by Sean Kim on 12/13/24.
//
import Foundation
struct NaviState: Equatable {
var act: NaviAction
var path: PathName
static func == (lhs: NaviState, rhs: NaviState) -> Bool {
return lhs.act == rhs.act && lhs.path == rhs.path
}
mutating func set(act: NaviAction = .ADD, path: PathName = .NONE) {
self.act = act
self.path = path
}
}
enum NaviAction: Hashable {
///
case ADD
///
case RESET
///
case POP
/// (path == NONE )
case MOVE
///
case NONE
/// FIRST = , MOVE =
}
enum PathName: Hashable {
case Intro
case Login
case Main
case NONE
}

View File

@ -0,0 +1,27 @@
//
// Network.swift
// AcaMate
//
// Created by Sean Kim on 12/10/24.
//
import Network
import Combine
class NetworkMonitor: ObservableObject {
static let shared = NetworkMonitor()
private let monitor = NWPathMonitor()
private let queue = DispatchQueue.global(qos: .background)
@Published var isConnected: Bool = true
private init() {
monitor.pathUpdateHandler = { [weak self] path in
DispatchQueue.main.async {
self?.isConnected = (path.status == .satisfied)
}
}
monitor.start(queue: queue)
}
}

View File

@ -6,9 +6,23 @@
//
import SwiftUI
import Combine
struct NetworkModifier: ViewModifier {
@ObservedObject private var networkMonitor = NetworkMonitor.shared
func body(content: Content) -> some View {
content
.onChange(of: networkMonitor.isConnected) { _ , new in
if new {
}
}
}
}
extension View {
func fullView(_ backColor: Color) -> some View{
func fullView(_ backColor: Color) -> some View {
return self
.frame(maxWidth: .infinity, maxHeight: .infinity)
.background(backColor)
@ -17,4 +31,10 @@ extension View {
func endTextEditing() {
UIApplication.shared.sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil)
}
func setNavigaion() -> some View {
self
.navigationBarBackButtonHidden(true)
.toolbar(.hidden, for: .navigationBar)
}
}

View File

@ -22,7 +22,7 @@ struct AcaMateApp: App {
var body: some Scene {
WindowGroup {
IntroView().onOpenURL { url in
NavigationView().onOpenURL { url in
if (AuthApi.isKakaoTalkLoginUrl(url)) {
_ = AuthController.handleOpenUrl(url: url)
}