🕶️

visionOS Tips: 自端末のIPv4 IPアドレス取得

2025/01/28に公開

AVP自身のIPv4 IPアドレスを取得する実装例。

実装

import Network

func getIPAddress() -> String? {
    var address: String?
    var ifaddr: UnsafeMutablePointer<ifaddrs>? = nil

    guard getifaddrs(&ifaddr) == 0 else { return nil }

    var ptr = ifaddr
    while ptr != nil {
        defer { ptr = ptr?.pointee.ifa_next }

        guard let interface = ptr else { continue }

        let addrFamily = interface.pointee.ifa_addr.pointee.sa_family
        guard addrFamily == UInt8(AF_INET) || addrFamily == UInt8(AF_INET6) else { continue }

        var hostname = [CChar](repeating: 0, count: Int(NI_MAXHOST))
        guard getnameinfo(interface.pointee.ifa_addr, socklen_t(interface.pointee.ifa_addr.pointee.sa_len),
                          &hostname, socklen_t(hostname.count), nil, socklen_t(0), NI_NUMERICHOST) == 0 else { continue }

        let ip = String(cString: hostname)
        let interfaceName = String(cString: interface.pointee.ifa_name)
        if interfaceName.hasPrefix("en") && isValidIPv4(ip) && isLocalIPAddress(ip) {
            address = ip
            break
        }
    }
    freeifaddrs(ifaddr)

    return address
}

private func isValidIPv4(_ ipAddress: String) -> Bool {
    let ipv4Regex = #"^((25[0-5]|2[0-4][0-9]|[0-1]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[0-1]?[0-9][0-9]?)$"#
    let predicate = NSPredicate(format: "SELF MATCHES %@", ipv4Regex)
    return predicate.evaluate(with: ipAddress)
}

private func isLocalIPAddress(_ ipAddress: String) -> Bool {
    let parts = ipAddress.split(separator: ".").compactMap { Int($0) }
    guard parts.count == 4 else { return false }

    if parts[0] == 10 {
        return true // 10.0.0.0/8
    } else if parts[0] == 172 && (16...31).contains(parts[1]) {
        return true // 172.16.0.0/12
    } else if parts[0] == 192 && parts[1] == 168 {
        return true // 192.168.0.0/16
    }
    return false
}

Discussion