본문 바로가기
Project/SwiftUI 블록와이드

[SwiftUI Project] 네트워크 모니터 추가하기 (유튜브 스타일)

by iOS_woo 2022. 10. 19.

인터넷에 연결되지 않았을 때 메시지
다시 인터넷 연결되면 메시지를 바꿔서 보여주고, 5초후에 내려갑니다.

카카오톡 먹통 이후 드디어 작업물을 새롭게 기록할 수 있게 되었네요! (짝짝짝)

 

이번에 구현해본 것은 네트워크 모니터를 활용해 연결 상태를 유저에게 피드백해주는 기능입니다. 

모든 어플에 구현되어 있는 필수 기능입니다. 

메세지를 보여주는 형태는 유튜브 앱에서 사용되는 스타일로 만들어 봤습니다. 

 

1. NWPathMonitor()로 Network Monitor를 작성해줍니다. 

import Foundation
import Network
import SwiftUI

class NetworkMonitor: ObservableObject {
    
    @Published var isConnected: Bool = true
    @Published var showAlert: Bool = false
    
    let monitor = NWPathMonitor()
    let queue = DispatchQueue(label: "Monitor")
    
    init() {
        monitor.pathUpdateHandler = { [weak self] path in
            DispatchQueue.main.async {
                    if path.status == .satisfied { <-- 연결상태
                        withAnimation {
                            self?.isConnected = true
                        }
                        DispatchQueue.main.asyncAfter(deadline: .now() + 5) {
                            withAnimation {
                                self?.showAlert = false
                            }
                        }
                    } else {
                        withAnimation {
                            self?.isConnected = false
                            self?.showAlert = true
                        }
                    }
            }
        }
        monitor.start(queue: queue)
    }
}

init() 안의 함수는 연결상태에 따라서 동작하게 될 코드입니다.

기본적으로 isConnected를 업데이트해주고, 인터넷이 다시 연결되었을 시  "인터넷에 다시 연결됨" 메세지와 함께 초록색으로 변경시켜주고 5초간 유저에게 보여준 후 메시지창이 사라져야 하기 때문에 showAlert 프로퍼티도 업데이트해줬습니다. 

withAnimation은 모든 동작들에 애니메이션 효과를 부여해줍니다. 

 

2. 앱 전체에서 사용하길 원했기 때문에 부모 뷰에 EnvironmentObject로 추가해주었습니다.

import SwiftUI

@main
struct SwiftUICoinApp: App {
    
    @StateObject private var viewModel = HomeViewModel()
    @StateObject private var monitor = NetworkMonitor() <-- 네트워크 모니터
    @State private var isNavigationBarHidden: Bool = true
    
    var body: some Scene {
        WindowGroup {
            NavigationView {

                VStack {
                    MyTabView()
                        .navigationBarTitle("Hidden Title")
                        .navigationBarHidden(self.isNavigationBarHidden)
                        .onAppear {
                            self.isNavigationBarHidden = true
                        }
                    if !monitor.isConnected || monitor.showAlert {
                        NetworkMissingView() <-- 메세지뷰를 넣어주었습니다.
                    }
                }
               
            }
            .environmentObject(viewModel)
            .environmentObject(monitor) <-- 모든 자식뷰가 Monitor에 엑세스 할 수 있습니다.
            .navigationViewStyle(StackNavigationViewStyle())
        }
    }
}

 

3. AlertView를 생성해줍니다. 

import SwiftUI

struct NetworkMissingView: View {
    
    @EnvironmentObject var monitor: NetworkMonitor <-- EnvironmentObject를 통해 상태가 모든 뷰와 공유됩니다. 
    
    var body: some View {
        Text(monitor.isConnected ? "인터넷에 다시 연결됨" : "연결되지 않음")
            .frame(width: UIScreen.main.bounds.width)
            .font(.footnote)
            .background((monitor.isConnected ? Color.theme.green : Color.black).ignoresSafeArea())
            .foregroundColor(Color.white)
            .animation(.easeInOut, value: monitor.showAlert)
    }
}

struct NetworkMissingVIew_Previews: PreviewProvider {
    static var previews: some View {
        NetworkMissingView()
            .previewLayout(.sizeThatFits)
    }
}

 

유튜브 스타일 네트워크 모니터 완료입니다!

 

그런데 한가지 문제가 있습니다..

저의 경우 구현 초기에는 원할하게 되었다가 어느 순간부터는 잘 작동하지 않는 모습을 보여주고 있는데요.

검색하여보니 저와 비슷한 문제가 종종 발생하는 것을 알 수 있었고, 시뮬레이터에 문제가 있는 것이 아닌가 생각하고 있습니다. 

스택오버플로우의 댓글들도 시뮬레이터에 문제가 있는 것 같다고 얘기를 해주고 있습니다.

SwiftUI, Xcode에 자잘한 버그가 너무 많아요...ㅠㅠ

추후 실제 기기에서 테스트해보고 또 다른 이슈 혹은 개선사항이 발견되면 업데이트하겠습니다!

 

 

비슷한 문제를 다루는 글:

 

Swift network monitor switches .satisfied and .unsatisfied statuses

I'm trying to monitor the network access of an iOS app. When I run the simulator for a first time with wifi turned ON I get the right message "We're connected!". But when I switch OFF the...

stackoverflow.com

구현 참고: 

 

댓글