Nik*_*nov 64 network-programming ios swift
我需要在Swift中获取iOS设备的IP地址.这不是关于此的其他问题的重复!我需要只获得WiFi IP地址,如果没有wifi地址 - 我需要处理它.Stack Overflow上有一些关于它的问题,但是只有返回ip地址的函数.例如(来自如何在swift中获取IP地址):
func getIFAddresses() -> [String] {
    var addresses = [String]()
    // Get list of all interfaces on the local machine:
    var ifaddr : UnsafeMutablePointer<ifaddrs> = nil
    if getifaddrs(&ifaddr) == 0 {
        // For each interface ...
        for (var ptr = ifaddr; ptr != nil; ptr = ptr.memory.ifa_next) {
            let flags = Int32(ptr.memory.ifa_flags)
            var addr = ptr.memory.ifa_addr.memory
            // Check for running IPv4, IPv6 interfaces. Skip the loopback interface.
            if (flags & (IFF_UP|IFF_RUNNING|IFF_LOOPBACK)) == (IFF_UP|IFF_RUNNING) {
                if addr.sa_family == UInt8(AF_INET) || addr.sa_family == UInt8(AF_INET6) {
                    // Convert interface address to a human readable string:
                    var hostname = [CChar](count: Int(NI_MAXHOST), repeatedValue: 0)
                    if (getnameinfo(&addr, socklen_t(addr.sa_len), &hostname, socklen_t(hostname.count),
                        nil, socklen_t(0), NI_NUMERICHOST) == 0) {
                            if let address = String.fromCString(hostname) {
                                addresses.append(address)
                            }
                    }
                }
            }
        }
        freeifaddrs(ifaddr)
    }
    return addresses
}
在这里,我得到2个值 - 来自移动互联网(我认为)的地址和我需要的WiFi地址.有没有其他方法来获得只有WiFi IP地址?
Mar*_*n R 108
根据几个SO线程(例如,什么是iOS网络接口名称?什么是pdp_ip?什么是ap?),iOS设备上的WiFi接口始终具有名称"en0".
你的代码(这似乎是我在如何在swift中获取IP地址的答案:)检索所有正在运行的网络接口的IP地址列表.它可以很容易地修改为只返回"en0"接口的IP地址,实际上这就是我最初在该线程上回答的内容(这只是如何以编程方式获取iphone的ip地址的答案的Swift转换):
// Return IP address of WiFi interface (en0) as a String, or `nil`
func getWiFiAddress() -> String? {
    var address : String?
    // Get list of all interfaces on the local machine:
    var ifaddr : UnsafeMutablePointer<ifaddrs> = nil
    if getifaddrs(&ifaddr) == 0 {
        // For each interface ...
        var ptr = ifaddr
        while ptr != nil {
            defer { ptr = ptr.memory.ifa_next }
            let interface = ptr.memory
            // Check for IPv4 or IPv6 interface:
            let addrFamily = interface.ifa_addr.memory.sa_family
            if addrFamily == UInt8(AF_INET) || addrFamily == UInt8(AF_INET6) {
                // Check interface name:
                if let name = String.fromCString(interface.ifa_name) where name == "en0" {
                    // Convert interface address to a human readable string:
                    var hostname = [CChar](count: Int(NI_MAXHOST), repeatedValue: 0)
                    getnameinfo(interface.ifa_addr, socklen_t(interface.ifa_addr.memory.sa_len),
                                &hostname, socklen_t(hostname.count),
                                nil, socklen_t(0), NI_NUMERICHOST)
                    address = String.fromCString(hostname)
                }
            }
        }
        freeifaddrs(ifaddr)
    }
    return address
}
用法:
if let addr = getWiFiAddress() {
    print(addr)
} else {
    print("No WiFi address")
}
更新Swift 3:除了在Swift 3中采用代码进行
 许多更改之外,迭代所有接口现在都可以使用新的通用
 sequence()函数:
千万不要忘记添加#include <ifaddrs.h>在你的桥接报
// Return IP address of WiFi interface (en0) as a String, or `nil`
func getWiFiAddress() -> String? {
    var address : String?
    // Get list of all interfaces on the local machine:
    var ifaddr : UnsafeMutablePointer<ifaddrs>?
    guard getifaddrs(&ifaddr) == 0 else { return nil }
    guard let firstAddr = ifaddr else { return nil }
    // For each interface ...
    for ifptr in sequence(first: firstAddr, next: { $0.pointee.ifa_next }) {
        let interface = ifptr.pointee
        // Check for IPv4 or IPv6 interface:
        let addrFamily = interface.ifa_addr.pointee.sa_family
        if addrFamily == UInt8(AF_INET) || addrFamily == UInt8(AF_INET6) {
            // Check interface name:
            let name = String(cString: interface.ifa_name)
            if  name == "en0" {
                // Convert interface address to a human readable string:
                var hostname = [CChar](repeating: 0, count: Int(NI_MAXHOST))
                getnameinfo(interface.ifa_addr, socklen_t(interface.ifa_addr.pointee.sa_len),
                            &hostname, socklen_t(hostname.count),
                            nil, socklen_t(0), NI_NUMERICHOST)
                address = String(cString: hostname)
            }
        }
    }
    freeifaddrs(ifaddr)
    return address
}
iAn*_*rag 19
创建桥接标题并包含#include <ifaddrs.h>在其中.
然后写这个方法
func getIFAddresses() -> [String] {
var addresses = [String]()
// Get list of all interfaces on the local machine:
var ifaddr : UnsafeMutablePointer<ifaddrs> = nil
if getifaddrs(&ifaddr) == 0 {
    // For each interface ...
    for (var ptr = ifaddr; ptr != nil; ptr = ptr.memory.ifa_next) {
        let flags = Int32(ptr.memory.ifa_flags)
        var addr = ptr.memory.ifa_addr.memory
        // Check for running IPv4, IPv6 interfaces. Skip the loopback interface.
        if (flags & (IFF_UP|IFF_RUNNING|IFF_LOOPBACK)) == (IFF_UP|IFF_RUNNING) {
            if addr.sa_family == UInt8(AF_INET) || addr.sa_family == UInt8(AF_INET6) {
                // Convert interface address to a human readable string:
                var hostname = [CChar](count: Int(NI_MAXHOST), repeatedValue: 0)
                if (getnameinfo(&addr, socklen_t(addr.sa_len), &hostname, socklen_t(hostname.count),
                    nil, socklen_t(0), NI_NUMERICHOST) == 0) {
                        if let address = String.fromCString(hostname) {
                            addresses.append(address)
                        }
                }
            }
        }
    }
    freeifaddrs(ifaddr)
}
  return addresses
}
当我在viewController中调用此方法时,就像   var arr : NSArray = self.getIFAddresses()我在我的控制台中得到完美的响应一样
IP :("10.0.0.94")
从这个数组你可以随时访问它.希望能帮助到你
Sag*_*ode 15
Swift 4 - 获取设备的IP地址:
添加   #include<ifaddrs.h>您的桥接标题.
这是获取IP地址所需的框架.
class func getIPAddress() -> String? {
        var address: String?
        var ifaddr: UnsafeMutablePointer<ifaddrs>? = nil
        if getifaddrs(&ifaddr) == 0 {
            var ptr = ifaddr
            while ptr != nil {
                defer { ptr = ptr?.pointee.ifa_next }
                let interface = ptr?.pointee
                let addrFamily = interface?.ifa_addr.pointee.sa_family
                if addrFamily == UInt8(AF_INET) || addrFamily == UInt8(AF_INET6) {
                    if let name: String = String(cString: (interface?.ifa_name)!), name == "en0" {
                        var hostname = [CChar](repeating: 0, count: Int(NI_MAXHOST))
                        getnameinfo(interface?.ifa_addr, socklen_t((interface?.ifa_addr.pointee.sa_len)!), &hostname, socklen_t(hostname.count), nil, socklen_t(0), NI_NUMERICHOST)
                        address = String(cString: hostname)
                    }
                }
            }
            freeifaddrs(ifaddr)
        }
        return address
}
Dan*_*orm 11
Swift 4.2 UIDevice扩展可避免强制拆包并支持蜂窝和有线ip地址:
import UIKit
extension UIDevice {
    private struct InterfaceNames {
        static let wifi = ["en0"]
        static let wired = ["en2", "en3", "en4"]
        static let cellular = ["pdp_ip0","pdp_ip1","pdp_ip2","pdp_ip3"]
        static let supported = wifi + wired + cellular
    }
    func ipAddress() -> String? {
        var ipAddress: String?
        var ifaddr: UnsafeMutablePointer<ifaddrs>?
        if getifaddrs(&ifaddr) == 0 {
            var pointer = ifaddr
            while pointer != nil {
                defer { pointer = pointer?.pointee.ifa_next }
                guard
                    let interface = pointer?.pointee,
                    interface.ifa_addr.pointee.sa_family == UInt8(AF_INET) || interface.ifa_addr.pointee.sa_family == UInt8(AF_INET6),
                    let interfaceName = interface.ifa_name,
                    let interfaceNameFormatted = String(cString: interfaceName, encoding: .utf8),
                    InterfaceNames.supported.contains(interfaceNameFormatted)
                    else { continue }
                var hostname = [CChar](repeating: 0, count: Int(NI_MAXHOST))
                getnameinfo(interface.ifa_addr,
                            socklen_t(interface.ifa_addr.pointee.sa_len),
                            &hostname,
                            socklen_t(hostname.count),
                            nil,
                            socklen_t(0),
                            NI_NUMERICHOST)
                guard
                    let formattedIpAddress = String(cString: hostname, encoding: .utf8),
                    !formattedIpAddress.isEmpty
                    else { continue }
                ipAddress = formattedIpAddress
                break
            }
            freeifaddrs(ifaddr)
        }
        return ipAddress
    }
}
用法:
UIDevice.current.ipAddress()
获取wifi,有线和蜂窝网络的IPAddress(swift 5)
func getIPAddress() -> String {
        var address: String?
        var ifaddr: UnsafeMutablePointer<ifaddrs>? = nil
        if getifaddrs(&ifaddr) == 0 {
            var ptr = ifaddr
            while ptr != nil {
                defer { ptr = ptr?.pointee.ifa_next }
                let interface = ptr?.pointee
                let addrFamily = interface?.ifa_addr.pointee.sa_family
                if addrFamily == UInt8(AF_INET) || addrFamily == UInt8(AF_INET6) {
                    // wifi = ["en0"]
                    // wired = ["en2", "en3", "en4"]
                    // cellular = ["pdp_ip0","pdp_ip1","pdp_ip2","pdp_ip3"]
                    let name: String = String(cString: (interface!.ifa_name))
                    if  name == "en0" || name == "en2" || name == "en3" || name == "en4" || name == "pdp_ip0" || name == "pdp_ip1" || name == "pdp_ip2" || name == "pdp_ip3" {
                        var hostname = [CChar](repeating: 0, count: Int(NI_MAXHOST))
                        getnameinfo(interface?.ifa_addr, socklen_t((interface?.ifa_addr.pointee.sa_len)!), &hostname, socklen_t(hostname.count), nil, socklen_t(0), NI_NUMERICHOST)
                        address = String(cString: hostname)
                    }
                }
            }
            freeifaddrs(ifaddr)
        }
        return address ?? ""
    }
如何使用
let strIPAddress : String = self.getIPAddress()
print("IPAddress :: \(strIPAddress)")
注意:在您的项目的Bridging-Header文件中添加以下内容
#include<ifaddrs.h>
另一个有点不同的解决方案是使用Ipify,这是一个免费的轻量级服务,您可以 ping 来获取您的 IP
这是他们的 Swift 示例:
let url = URL(string: "https://api.ipify.org")
do {
    if let url = url {
        let ipAddress = try String(contentsOf: url)
        print("My public IP address is: " + ipAddress)
    }
} catch let error {
    print(error)
}
您可以使用以下代码获取IP地址:
注意:我已经使用了可访问性,以便在WiFi被更改为另一个时捕获新的IP地址.
在Podfile档案中  
pod 'ReachabilitySwift' 然后 install pod
在AppDelegate.swift档案中import ReachabilitySwift
注意:如果它提示无法找到ReachabilitySwift模块的错误,则只需复制并粘贴它即可.有用!
didFinishLaunchingOptions 功能
NotificationCenter.default.addObserver(self, selector: #selector(self.reachabilityChanged), name: ReachabilityChangedNotification, object: reachability)
do{
    try reachability.startNotifier()
}
catch {
    print("could not start reachability notifier")
} 
然后复制粘贴到AppDelegate文件中的代码下面
func reachabilityChanged(note: NSNotification) {
    let reachability = note.object as! Reachability
    if reachability.isReachable {
        if reachability.isReachableViaWiFi {
            print("Reachable via WiFi")
        } else {
            print("Reachable via Cellular")
        }
        setIPAddress()
    } else {
        ipAddress = "" // No IP captures
        print("Network not reachable")
    }
}
func setIPAddress() {
    if let addr = self.getWiFiAddress() {
        print("ipAddress : \(addr)")
        ipAddress = addr
    } else {
        ipAddress = "" // No IP captures
        print("No WiFi address")
    }
}
// Return IP address of WiFi interface (en0) as a String, or `nil`
func getWiFiAddress() -> String? {
    var address : String?
    // Get list of all interfaces on the local machine:
    var ifaddr : UnsafeMutablePointer<ifaddrs>?
    guard getifaddrs(&ifaddr) == 0 else { return nil }
    guard let firstAddr = ifaddr else { return nil }
    // For each interface ...
    for ifptr in sequence(first: firstAddr, next: { $0.pointee.ifa_next }) {
        let interface = ifptr.pointee
        // Check for IPv4 or IPv6 interface:
        let addrFamily = interface.ifa_addr.pointee.sa_family
        if addrFamily == UInt8(AF_INET) || addrFamily == UInt8(AF_INET6) {
            // Check interface name:
            let name = String(cString: interface.ifa_name)
            if  name == "en0" {
                // Convert interface address to a human readable string:
                var addr = interface.ifa_addr.pointee
                var hostname = [CChar](repeating: 0, count: Int(NI_MAXHOST))
                getnameinfo(&addr, socklen_t(interface.ifa_addr.pointee.sa_len),
                            &hostname, socklen_t(hostname.count),
                            nil, socklen_t(0), NI_NUMERICHOST)
                address = String(cString: hostname)
            }
        }
    }
    freeifaddrs(ifaddr)
    return address
}
在Bridging-Header文件中添加它 #include<ifaddrs.h>
如果您没有此文件,则可以创建它检查此链接
6.
func applicationWillEnterForeground(_ application: UIApplication) {
        // Post notification
        NotificationCenter.default.post(name: ReachabilityChangedNotification, object: reachability)
        // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
    }
如果要删除观察者,则:
reachability.stopNotifier()  
NSNotificationCenter.defaultCenter().removeObserver(self,name: ReachabilityChangedNotification,object: reachability)
Swift 5 清理
我更新了上面的答案,以消除任何强制展开和一些 SwiftLint 清理。
 class func getIPAddress() -> String? {
        var address: String?
        var ifaddr: UnsafeMutablePointer<ifaddrs>?
        if getifaddrs(&ifaddr) == 0 {
            var ptr = ifaddr
            while ptr != nil {
                defer { ptr = ptr?.pointee.ifa_next }
                let interface = ptr?.pointee
                let addrFamily = interface?.ifa_addr.pointee.sa_family
                if addrFamily == UInt8(AF_INET) || addrFamily == UInt8(AF_INET6),
                    let cString = interface?.ifa_name,
                    String(cString: cString) == "en0",
                    let saLen = (interface?.ifa_addr.pointee.sa_len) {
                    var hostname = [CChar](repeating: 0, count: Int(NI_MAXHOST))
                    let ifaAddr = interface?.ifa_addr
                    getnameinfo(ifaAddr,
                                socklen_t(saLen),
                                &hostname,
                                socklen_t(hostname.count),
                                nil,
                                socklen_t(0),
                                NI_NUMERICHOST)
                    address = String(cString: hostname)
                }
            }
            freeifaddrs(ifaddr)
        }
        return address
    }
NWInterface.InterfaceType基于上述一些答案的扩展:
import Network
extension NWInterface.InterfaceType {
    var names : [String]? {
        switch self {
        case .wifi: return ["en0"]
        case .wiredEthernet: return ["en2", "en3", "en4"]
        case .cellular: return ["pdp_ip0","pdp_ip1","pdp_ip2","pdp_ip3"]
        default: return nil
        }
    }
    func address(family: Int32) -> String?
    {
        guard let names = names else { return nil }
        var address : String?
        for name in names {
            guard let nameAddress = self.address(family: family, name: name) else { continue }
            address = nameAddress
            break
        }
        return address
    }
    func address(family: Int32, name: String) -> String? {
        var address: String?
        // Get list of all interfaces on the local machine:
        var ifaddr: UnsafeMutablePointer<ifaddrs>?
        guard getifaddrs(&ifaddr) == 0, let firstAddr = ifaddr else { return nil }
        // For each interface ...
        for ifptr in sequence(first: firstAddr, next: { $0.pointee.ifa_next }) {
            let interface = ifptr.pointee
            let addrFamily = interface.ifa_addr.pointee.sa_family
            if addrFamily == UInt8(family)
            {
                // Check interface name:
                if name == String(cString: interface.ifa_name) {
                    // Convert interface address to a human readable string:
                    var hostname = [CChar](repeating: 0, count: Int(NI_MAXHOST))
                    getnameinfo(interface.ifa_addr, socklen_t(interface.ifa_addr.pointee.sa_len),
                                &hostname, socklen_t(hostname.count),
                                nil, socklen_t(0), NI_NUMERICHOST)
                    address = String(cString: hostname)
                }
            }
        }
        freeifaddrs(ifaddr)
        return address
    }
    var ipv4 : String? { self.address(family: AF_INET) }
    var ipv6 : String? { self.address(family: AF_INET6) }
}
用法:
对于蜂窝的 ipv4:NWInterface.InterfaceType.cellular.ipv4
小智 5
此类通过 NWPathMonitor 监视设备接口。您可以设置一个更新处理程序来通知您有关接口状态更改的信息。选择是否要跟踪 ipv4 或 ipv6 并检查 status.interfaceType == .wifi 以查看您的活动接口是否为 wifi
用法:
let monitor = IPMonitor(ipType: .ipv4) 
monitor.pathUpdateHandler = { status in 
  print("\(status.debugDescription)")
}
班级:
import Foundation
import Network
class IPMonitor {
    
    enum InterfaceType: String {
        case cellular = "cellular"
        case wifi = "wifi"
        case wired = "wired"
        case loopback = "loopback"
        case other = "other"
        case notFound = "not found"
    }
    
    enum IPType: String {
        case ipv4 = "IPv4"
        case ipv6 = "ipV6"
        case unknown = "unknown"
    }
    
    struct Status {
        var name = "unknown"
        var interfaceType: InterfaceType = InterfaceType.notFound
        var ip: [String] = []
        var ipType: IPType = IPType.unknown
        
        var debugDescription: String {
            let result = "Interface: \(name)/\(interfaceType.rawValue), \(ipType.rawValue)\(ip.debugDescription)"
            return result
        }
    }
    
    private let monitor = NWPathMonitor()
    private let queue = DispatchQueue(label: "ip_monitor_queue")
    
    final var pathUpdateHandler: ((Status) -> Void)?
    
    init(ipType: IPType) {
        monitor.pathUpdateHandler = { path in
            let name = self.getInterfaceName(path: path)
            let type = self.getInterfaceType(path: path)
            let ip = self.getIPAddresses(interfaceName: name, ipType: ipType)
            let status = Status(name: name, interfaceType: type, ip: ip, ipType: ipType)
            //print("\(status)")
            self.pathUpdateHandler?(status)
        }
        monitor.start(queue: queue)
    }
    
    private func getInterfaceName(path: NWPath) -> String {
        if let name = path.availableInterfaces.first?.name {
            return name
        }
        return "unknown"
    }
    
    private func getInterfaceType(path: NWPath) -> InterfaceType {
        if let type = path.availableInterfaces.first?.type {
            switch type {
            case NWInterface.InterfaceType.cellular:
                return InterfaceType.cellular
            case NWInterface.InterfaceType.wifi:
                return InterfaceType.wifi
            case NWInterface.InterfaceType.wiredEthernet:
                return InterfaceType.wired
            case NWInterface.InterfaceType.loopback:
                return InterfaceType.loopback
            default:
                return InterfaceType.other
            }
        }
        
        return InterfaceType.notFound
    }
    
    private func getIPAddresses(interfaceName: String, ipType: IPType)-> [String]{
        var addresses: [String] = []
        var ifaddr: UnsafeMutablePointer<ifaddrs>? = nil
        if getifaddrs(&ifaddr) == 0 {
            var ptr = ifaddr
            while ptr != nil {
                defer { ptr = ptr?.pointee.ifa_next }
                let interface = ptr?.pointee
                let addrFamily = interface?.ifa_addr.pointee.sa_family
                if (addrFamily == UInt8(AF_INET) && ipType == .ipv4)
                    || (addrFamily == UInt8(AF_INET6) && ipType == .ipv6) {
                    let name = String(cString: (interface?.ifa_name)!)
                    if name == interfaceName {
                        var hostname = [CChar](repeating: 0, count: Int(NI_MAXHOST))
                        getnameinfo(interface?.ifa_addr, socklen_t((interface?.ifa_addr.pointee.sa_len)!), &hostname, socklen_t(hostname.count), nil, socklen_t(0), NI_NUMERICHOST)
                        addresses.append(String(cString: hostname))
                    }
                }
            }
        }
        freeifaddrs(ifaddr)
        
        return addresses
    }
}
| 归档时间: | 
 | 
| 查看次数: | 63487 次 | 
| 最近记录: |