【SwiftUI】NWPathMonitorを使用して、ネットワーク通信状態を確認する

2022.07.27

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

ネットワーク通信されていない時は、「特定の表示を出したい」等があると思います。今回はApple標準のNWPathMonitorを使用して、ネットワーク通信状態に応じてViewを変更するものを作っていきたいと思います。

環境

  • Xcode 13.3
  • iOS 15.5

作ったもの

ネットワーク状態が切れると画面が黒くなり、ネットワークが繋がると画面が青くなります。

NetworkState

NWPathMonitor

ネットワークの変更を監視して対応するために使用するオブザーバーです。func start(queue: DispatchQueue)を使用することでパスの変更を監視することが出来ます。

今回はこのNWPathMonitorを使用して、ネットワーク状態を監視するObservableObjectを作成していきます。

MonitoringNetworkState

MonitoringNetworkStateというネットワーク状態を監視するObservableObjectを作成します。

import Foundation
import Network

class MonitoringNetworkState: ObservableObject {

    private let monitor = NWPathMonitor()
    private let queue = DispatchQueue.global(qos: .background)

    @Published var isConnected = false

    init() {
        monitor.start(queue: queue)

        monitor.pathUpdateHandler = { path in
            if path.status == .satisfied {
                DispatchQueue.main.async {
                    self.isConnected = true
                }
            } else {
                DispatchQueue.main.async {
                    self.isConnected = false
                }
            }
        }
    }
}

プロパティ

private let monitor = NWPathMonitor()
private let queue = DispatchQueue.global(qos: .background)

@Published var isConnected = false

ネットワーク状態を監視する為のNWPathMonitor()とパス配信するイベントキューDispatchQueue.global(qos: .background)を宣言します。

そして、ネットワーク状態をパブリッシュする為の変数@Published var isConnectedも用意します。

init

init() {
    // パスモニターの開始
    monitor.start(queue: queue)

    // ネットワークパスが更新されたら行いたい処理を記述する
    monitor.pathUpdateHandler = { path in
        if path.status == .satisfied {
            DispatchQueue.main.async {
                self.isConnected = true
            }
        } else {
            DispatchQueue.main.async {
                self.isConnected = false
            }
        }
    }
}

MonitoringNetworkStateの初期化時にパスモニターを開始し、ネットワークパスの更新を監視できるようにします。そして、パスのstatus.satisfied(満足した)状態の場合はisConnectedtrueを返し、そうでない場合はfalseを返すようにしています。

ContentView

あとは、MonitoringNetworkState.isConnectedの値を見て処理を切り分ければ完成です。

import SwiftUI

struct ContentView: View {

    @EnvironmentObject var networkState: MonitoringNetworkState

    var body: some View {
        ZStack {
            Rectangle()
                .fill(networkState.isConnected ? .blue : .black)

            Text(networkState.isConnected ? "Good connection" : "Bad connection")
                .foregroundColor(.white)
        }
    }
}

先ほど、作成したObservableObjectMonitoringNetworkStateEnvironmentObjectとして定義します。

あとは、networkState.isConnectedtrueなら背景色を青にして、falseなら黒に変更するようにしました。またテキストの内容もisConnectedの値によって変更するようにしました。

@main

上記ContentViewではEnvironmentObjectを使用しているので、ContentView呼出時に、environmentObjectModifierを使用し、MonitoringNetworkStateを渡します。サブ階層にObservableObjectを提供する為には必要になります。

import SwiftUI

@main
struct MonitoringNetworkApp: App {
    var body: some Scene {
        WindowGroup {
            ContentView()
                .environmentObject(MonitoringNetworkState())
        }
    }
}

これで完成です。

おわりに

ネットワーク通信状態をみるのにライブラリを使用せずとも標準のものを使用して監視できることが分かりました。NWPathMonitorSwiftUIで限られたものでも無いので、UIKit製のアプリでも同じように使うことが出来ます。またUIKitでも試してみたいと思います。

今回のコードはGitHubに置いております。

この記事が誰かの助けになれば幸いです。

参考