Last active
January 24, 2025 06:08
-
-
Save treastrain/9913abfc46125cc904a1ac984d4656f7 to your computer and use it in GitHub Desktop.
NWPathMonitor のサンプル
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// NetworkPlaygroundApp.swift | |
// NetworkPlayground | |
// | |
// Created by treastrain / Tanaka Ryoga on 2021/09/28. | |
// | |
import SwiftUI | |
import Network | |
class NetworkMonitor: ObservableObject { | |
@Published var status = "Waiting..." | |
@Published var availableInterfaces = "" | |
@Published var gateways = "" | |
@Published var supportsIPv4 = "" | |
@Published var supportsIPv6 = "" | |
@Published var supportsDNS = "" | |
@Published var isConstrained = "" | |
@Published var isExpensive = "" | |
@Published var debugDescription = "" | |
@Published var localEndpoint = "" | |
@Published var remoteEndpoint = "" | |
@Published var unsatisfiedReason = "" | |
let monitor = NWPathMonitor() | |
func start() { | |
monitor.pathUpdateHandler = { path in | |
DispatchQueue.main.async { | |
self.status = "\(path.status)" | |
self.availableInterfaces = "\(path.availableInterfaces)" | |
self.gateways = "\(path.gateways)" | |
self.supportsIPv4 = "\(path.supportsIPv4)" | |
self.supportsIPv6 = "\(path.supportsIPv6)" | |
self.supportsDNS = "\(path.supportsDNS)" | |
self.isConstrained = "\(path.isConstrained)" | |
self.isExpensive = "\(path.isExpensive)" | |
self.debugDescription = "\(path.debugDescription)" | |
self.localEndpoint = "\(path.localEndpoint)" | |
self.remoteEndpoint = "\(path.remoteEndpoint)" | |
self.unsatisfiedReason = "\(path.unsatisfiedReason)" | |
} | |
print("--------------------") | |
print("status:", path.status) | |
print("availableInterfaces:", path.availableInterfaces) | |
print("gateways:", path.gateways) | |
print("supportsIPv4:", path.supportsIPv4) | |
print("supportsIPv6:", path.supportsIPv6) | |
print("supportsDNS:", path.supportsDNS) | |
print("isConstrained:", path.isConstrained) | |
print("isExpensive:", path.isExpensive) | |
print("debugDescription:", path.debugDescription) | |
print("localEndpoint:", path.localEndpoint) | |
print("remoteEndpoint:", path.remoteEndpoint) | |
print("unsatisfiedReason:", path.unsatisfiedReason) | |
print("--------------------") | |
} | |
monitor.start(queue: .global(qos: .background)) | |
} | |
func cancel() { | |
monitor.cancel() | |
} | |
} | |
@main | |
struct NetworkPlaygroundApp: App { | |
@ObservedObject var networkMonitor = NetworkMonitor() | |
init() { | |
networkMonitor.start() | |
} | |
var body: some Scene { | |
WindowGroup { | |
VStack(alignment: .leading) { | |
Group { | |
Text("status: ") + Text(networkMonitor.status) | |
Text("availableInterfaces: ") + Text(networkMonitor.availableInterfaces) | |
Text("gateways: ") + Text(networkMonitor.gateways) | |
Text("supportsIPv4: ") + Text(networkMonitor.supportsIPv4) | |
Text("supportsIPv6: ") + Text(networkMonitor.supportsIPv6) | |
Text("supportsDNS: ") + Text(networkMonitor.supportsDNS) | |
Text("isConstrained: ") + Text(networkMonitor.isConstrained) | |
Text("isExpensive: ") + Text(networkMonitor.isExpensive) | |
} | |
Group { | |
Text("debugDescription: ") + Text(networkMonitor.debugDescription) | |
Text("localEndpoint: ") + Text(networkMonitor.localEndpoint) | |
Text("remoteEndpoint: ") + Text(networkMonitor.remoteEndpoint) | |
Text("unsatisfiedReason: ") + Text(networkMonitor.unsatisfiedReason) | |
} | |
} | |
.font(.system(.body, design: .monospaced)) | |
} | |
} | |
} | |
/** | |
# 以下、いろんな端末・環境で動かしてみた例 | |
## iPhone 13 Pro、機内モードにより Wi-Fi・Cellular・Bluetooth オフ | |
-------------------- | |
status: unsatisfied | |
availableInterfaces: [] | |
gateways: [] | |
supportsIPv4: false | |
supportsIPv6: false | |
supportsDNS: false | |
isConstrained: false | |
isExpensive: false | |
debugDescription: unsatisfied (No network route) | |
localEndpoint: nil | |
remoteEndpoint: nil | |
unsatisfiedReason: notAvailable | |
-------------------- | |
## iPhone 13 Pro、Cellular (5G)、Wi-Fi (IPv6) | |
`availableInterfaces: [en0, pdp_ip0]` ということで、Wi-Fi と Cellular が使えることがわかる | |
一度 `en0, ipv6, dns` になり、その後 IPv4 over IPv6 になるところが確認できる | |
-------------------- | |
status: satisfied | |
availableInterfaces: [en0, pdp_ip0] | |
gateways: [fe80::fab7:97ff:fef8:50dc%en0%en0.0] | |
supportsIPv4: false | |
supportsIPv6: true | |
supportsDNS: true | |
isConstrained: false | |
isExpensive: false | |
debugDescription: satisfied (Path is satisfied), interface: en0, ipv6, dns | |
localEndpoint: nil | |
remoteEndpoint: nil | |
unsatisfiedReason: notAvailable | |
-------------------- | |
-------------------- | |
status: satisfied | |
availableInterfaces: [en0, pdp_ip0] | |
gateways: [192.168.10.1:0, fe80::fab7:97ff:fef8:50dc%en0%en0.0] | |
supportsIPv4: true | |
supportsIPv6: true | |
supportsDNS: true | |
isConstrained: false | |
isExpensive: false | |
debugDescription: satisfied (Path is satisfied), interface: en0, ipv4, ipv6, dns | |
localEndpoint: nil | |
remoteEndpoint: nil | |
unsatisfiedReason: notAvailable | |
-------------------- | |
## iPhone 13 Pro、Cellular (5G) | |
`availableInterfaces: [pdp_ip0]` ということで、Cellular のみ使えることがわかる | |
`isExpensive: true` となっており、セルラー通信である可能性がみられる | |
-------------------- | |
status: satisfied | |
availableInterfaces: [pdp_ip0] | |
gateways: [10.170.192.37:0, fe80::39cd:1f70:205:e71a%pdp_ip0%pdp_ip0.0] | |
supportsIPv4: true | |
supportsIPv6: true | |
supportsDNS: true | |
isConstrained: false | |
isExpensive: true | |
debugDescription: satisfied (Path is satisfied), interface: pdp_ip0[lte], ipv4, ipv6, dns, expensive | |
localEndpoint: nil | |
remoteEndpoint: nil | |
unsatisfiedReason: notAvailable | |
-------------------- | |
## iPad Air (4th gen. Wi-Fi モデル)、Wi-Fi (IPv6) | |
`availableInterfaces: [en0]` ということで、Wi-Fi のみ使えることがわかる | |
一度 `en0, ipv6, dns` になり、その後 IPv4 over IPv6 になるところが確認できる | |
-------------------- | |
status: satisfied | |
availableInterfaces: [en0] | |
gateways: [fe80::fab7:97ff:fef8:50dc%en0%en0.0] | |
supportsIPv4: false | |
supportsIPv6: true | |
supportsDNS: true | |
isConstrained: false | |
isExpensive: false | |
debugDescription: satisfied (Path is satisfied), interface: en0, ipv6, dns | |
localEndpoint: nil | |
remoteEndpoint: nil | |
unsatisfiedReason: notAvailable | |
-------------------- | |
-------------------- | |
status: satisfied | |
availableInterfaces: [en0] | |
gateways: [192.168.10.1:0, fe80::fab7:97ff:fef8:50dc%en0%en0.0] | |
supportsIPv4: true | |
supportsIPv6: true | |
supportsDNS: true | |
isConstrained: false | |
isExpensive: false | |
debugDescription: satisfied (Path is satisfied), interface: en0, ipv4, ipv6, dns | |
localEndpoint: nil | |
remoteEndpoint: nil | |
unsatisfiedReason: notAvailable | |
-------------------- | |
## iPad Air (4th gen. Wi-Fi モデル)、Ethernet(有線LAN)接続 | |
`availableInterfaces: [en3]` ということで、Ethernet(有線LAN)接続であることがわかる | |
-------------------- | |
status: satisfied | |
availableInterfaces: [en3] | |
gateways: [192.168.10.1:0, fe80::fab7:97ff:fef8:50dc%en0%en3.0] | |
supportsIPv4: true | |
supportsIPv6: true | |
supportsDNS: true | |
isConstrained: false | |
isExpensive: false | |
debugDescription: satisfied (Path is satisfied), interface: en3, ipv4, ipv6, dns | |
localEndpoint: nil | |
remoteEndpoint: nil | |
unsatisfiedReason: notAvailable | |
-------------------- | |
## iPad Air (4th gen. Wi-Fi モデル)、Ethernet(有線LAN)接続されていて、Wi-Fi にも接続されている | |
`availableInterfaces: [en3, en0]` ということで、Ethernet(有線LAN)と Wi-Fi の両方で接続でされていることがわかる | |
-------------------- | |
status: satisfied | |
availableInterfaces: [en3, en0] | |
gateways: [192.168.10.1:0, fe80::fab7:97ff:fef8:50dc%en0%en3.0] | |
supportsIPv4: true | |
supportsIPv6: true | |
supportsDNS: true | |
isConstrained: false | |
isExpensive: false | |
debugDescription: satisfied (Path is satisfied), interface: en3, ipv4, ipv6, dns | |
localEndpoint: nil | |
remoteEndpoint: nil | |
unsatisfiedReason: notAvailable | |
-------------------- | |
## iPad Air (4th gen. Wi-Fi モデル)、Wi-Fi 経由で Cellular (5G) に接続された iPhone 13 Pro にテザリングして接続 | |
`isConstrained: true` ということで、Low Data Mode(省データモード)が使われていることがわかる | |
-------------------- | |
status: satisfied | |
availableInterfaces: [en0] | |
gateways: [172.20.10.1:0, fe80::f465:a6ff:fef6:f764%en0%en0.0] | |
supportsIPv4: true | |
supportsIPv6: true | |
supportsDNS: true | |
isConstrained: true | |
isExpensive: false | |
debugDescription: satisfied (Path is satisfied), interface: en0, ipv4, ipv6, dns, constrained | |
localEndpoint: nil | |
remoteEndpoint: nil | |
unsatisfiedReason: notAvailable | |
-------------------- | |
## iPad Air (4th gen. Wi-Fi モデル)、Bluetooth 経由で Cellular (5G) に接続された iPhone 13 Pro にテザリングして接続 | |
`isExpensive: true` となっており、Bluetooth 通信である可能性がみられる | |
-------------------- | |
status: satisfied | |
availableInterfaces: [en4] | |
gateways: [172.20.10.1:0, fe80::f465:a6ff:fef6:f764%en0%en4.0] | |
supportsIPv4: true | |
supportsIPv6: true | |
supportsDNS: true | |
isConstrained: false | |
isExpensive: true | |
debugDescription: satisfied (Path is satisfied), interface: en4, ipv4, ipv6, dns, expensive | |
localEndpoint: nil | |
remoteEndpoint: nil | |
unsatisfiedReason: notAvailable | |
-------------------- | |
*/ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment