글자 그대로 Apple이 제공하는 다양한 플랫폼에서 네트워크 연결성을 모니터링할 수 있는 역할, 뿐만 아니라 인터넷 연결, 셀룰러 데이터 인지 파악
각 다양한 인터페이스마다 다양한 적절히 조치를 취하는 것이 가능
Singleton 객체 만들기
final class NetworkCheck {
static let shared = NetworkCheck()
private let queue = DispatchQueue.global()
private let monitor: NWPathMonitor
private init() {
self.monitor = NWPathMonitor()
}
}
먼저 NetworkCheck라는 Singleton 디자인으로 구현된 클래스를 제작. 왜냐하면 네트워크 연결 상태를 체크하는 것은 앱을 대표해서 1개로 족하기 때문
네트워크를 체크하는 것은 항상 비동기로 이루어져야함. 왜냐하면 언제, 어디서 네트워크 연결이 불안정해지기 때문에 그것을 대비해서 Main Thread보다는 Global Thread에서 감지하는 것이 당연
이제 NetworkCheck가 초기화되면 NWPathMonitor를 초기화
네트워크 감지 시작하기
final class NetworkCheck {
static let shared = NetworkCheck()
private let queue = DispatchQueue.global()
private let monitor: NWPathMonitor
// monotior 초기화
private init() {
self.monitor = NWPathMonitor()
}
// Network Monitoring 시작
public func startMonitoring() {
self.monitor.start(queue: queue)
self.monitor.pathUpdateHandler = { path in
}
}
}
startMonitoring() 메서드에서 먼저 monitor의 start(queue:)를 호출, 여기에는 우리가 먼저 정의한 Global Queue를 주입
이제 네트워크 변경이 감지되면, monitor의 pathUpdateHandler를 통해 클로저로 반환
우리는 이 클로저 로직에 UI를 업데이트하는 로직을 구현
UI 관련된 프로퍼티 준비하기
final class NetworkCheck {
// ...
public private(set) var isConnected: Bool = false
public private(set) var topVCIsNetworkVC: Bool = false
private var topVC: UIViewController? {
let scenes = UIApplication.shared.connectedScenes
let windowScene = scenes.first as? UIWindowScene
let window = windowScene?.windows.first
return window?.rootViewController
}
// ...
}
isConnected는 현재 네트워크 연결 상태를 저장해주는 Boolean 프로퍼티입니다. 왜냐하면 pathUpdateHandler의 path는 여러 번 호출되어서 이것을 단 한 번의 시그널로 바꿔주는 역할을 합니다.
topVCIsNetworkVC는 현재 가장 상위의 있는 ViewController가 NetworkVC인지 판단합니다. NetworkVC는 네트워크 연결이 불안정할 때 나타나는 ViewController입니다.
topVC는 현재 상위 뷰에 있는 ViewController를 참조할 수 있는 프로퍼티입니다. NetworkCheck 클래스는 UI와 완전히 독립되어 있는 객체이기떄문에, UIApplication.shared를 참조하여 다른 화면으로 이동할 수 있도록 하는 징검다리 역할을 합니다.
pathUpdateHandler 로직 구성하기
final class NetworkCheck {
// ...
// Network Monitoring 시작
public func startMonitoring() {
self.monitor.start(queue: queue)
self.monitor.pathUpdateHandler = { [weak self] path in
guard let self = self else { return }
self.isConnected = path.status == .satisfied
if self.isConnected && self.topVCIsNetworkVC {
// 네트워크와 연결됨, 제일 위에 뷰가 NetworkVC임. -> NetworkVC 사라지기
self.dismissNetworkVC()
}
if self.isConnected == false && self.topVCIsNetworkVC == false {
// 네트워크와 연결안됨, 제일 위에 뷰가 NetworkVC가 아님. -> NetworkVC 보여주기
self.presentNetworkVC()
}
}
}
// ...
}
path.status는 NWPath.Status라는 enum타입을 가지고 있습니다.
satisfied는 네트워크 연결이 정상적으로 연결되어 있는 경우를 말합니다.
unsatisfied는 네트워크 연결이 끊겨있는 상태입니다.
requiresConnection는 네트워크 연결을 시도하고 있는 상태입니다.
이 세 가지 경우 중 satisfied를 제외한 나머지 경우는 모두 네트워크 연결이 정상적이기 않기때문에, satisfied 상태만 고려를 해주었습니다.
self.isConnected = path.status == .satisfied를 통해 self.isConnected의 상태 값을 변경해줍니다.