ios Swift - 获取设备的 WIFI IP 地址

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/30748480/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-31 06:19:37  来源:igfitidea点击:

Swift - Get device's WIFI IP Address

iosswiftnetwork-programming

提问by Nikita Zernov

I need to get IP Address of iOS device in Swift. This is not a duplicate of other questions about this! I need to get only WiFi IP address, if there is no wifi ip address - I need to handle it. There are a few questions about it on Stack Overflow, but there are only functions that return ip addresses. For example (from How to get Ip address in swift):

我需要在 Swift 中获取 iOS 设备的 IP 地址。这不是与此相关的其他问题的重复!我只需要获取 WiFi IP 地址,如果没有 WiFi IP 地址 - 我需要处理它。Stack Overflow 上有一些关于它的问题,但只有返回 ip 地址的函数。例如(来自How to get Ip address in swift):

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
}

Here I get 2 values - address from mobile internet(I think) and WiFi address I need. Is there any other way to get ONLY WiFi IP Address?

在这里我得到 2 个值 - 来自移动互联网的地址(我认为)和我需要的 WiFi 地址。有没有其他方法可以获取唯一的 WiFi IP 地址?

回答by Martin R

According to several SO threads (e.g. What exactly means iOS networking interface name? what's pdp_ip ? what's ap?), the WiFi interface on an iOS device always has then name "en0".

根据几个 SO 线程(例如,iOS 网络接口名称究竟是什么意思?pdp_ip 是什么?ap 是什么?),iOS 设备上的 WiFi 接口始终具有名称“en0”。

Your code (which seems to be what I answered at How to get Ip address in swift:) retrieves a list of the IP addresses of allrunning network interfaces. It can easily be modified to return only the IP address of the "en0" interface, and actually that is what I originallyhad answered at that thread (and this is just a Swift translation of the answer to how to get ip address of iphone programmatically):

您的代码(这似乎是我在How to get Ip address in swift 中回答的内容:)检索所有正在运行的网络接口的 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
}

Usage:

用法:

if let addr = getWiFiAddress() {
    print(addr)
} else {
    print("No WiFi address")
}


Update for Swift 3:In addition to adopting the code to the many changes in Swift 3, iterating over all interfaces can now use the new generalized sequence()function:

Swift 3 的更新:除了采用Swift 3 中许多更改的代码之外 ,迭代所有接口现在可以使用新的通用 sequence()函数:

Do NOTforget to add #include <ifaddrs.h>in your bridging header

千万不要忘记添加#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: { 
func getAddress(for network: Network) -> 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: { 
enum Network: String {
    case wifi = "en0"
    case cellular = "pdp_ip0"
    //... case ipv4 = "ipv4"
    //... case ipv6 = "ipv6"
}
.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 == network.rawValue { // 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 }
.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 }


For those of you who came looking for more than the WIFI IP you could modify this code a little

对于那些来寻找不仅仅是 WIFI 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
}
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
}

Then we have access to the cellular IP as well.

然后我们也可以访问蜂窝 IP。

guard let wifiIp = getAddress(for: .wifi) else { return }

guard let wifiIp = getAddress(for: .wifi) else { return }

&

&

guard let cellularIp = getAddress(for: .cellular) else { return }

guard let cellularIp = getAddress(for: .cellular) else { return }

回答by iAnurag

Create bridging header and Include #include <ifaddrs.h>in it.

创建桥接头并包含#include <ifaddrs.h>在其中。

then write this method

然后写这个方法

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
    }

}

when I call this method in my viewController like var arr : NSArray = self.getIFAddresses()I get perfect response in my console like

当我在 viewController 中调用此方法时,就像 var arr : NSArray = self.getIFAddresses()我在控制台中得到完美的响应一样

IP :( "10.0.0.94" )

IP :(“10.0.0.94”)

from this array you can access it where ever u want. Hope it helps

从这个数组你可以在任何你想要的地方访问它。希望能帮助到你

回答by Sagar Sukode

Swift 4 - Get device's IP Address:

Swift 4 - 获取设备的 IP 地址:

Add #include<ifaddrs.h>in your bridging header.

添加 #include<ifaddrs.h>您的桥接头。

This is the framework needed to get IP address.

这是获取 IP 地址所需的框架。

UIDevice.current.ipAddress()

回答by Daniel Storm

Swift 4.2 UIDeviceextension that avoids force unwraps and supports cellular and wired ip addresses:

UIDevice避免强制解包并支持蜂窝和有线 IP 地址的Swift 4.2扩展:

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 ?? ""
    }

Usage:

用法:

let strIPAddress : String = self.getIPAddress()
print("IPAddress :: \(strIPAddress)")

回答by Hardik Thakkar

To get IPAddress for wifi , wired, and cellular (swift 5)

获取 wifi、有线和蜂窝的 IP 地址 (swift 5)

#include<ifaddrs.h>

How to use

如何使用

NotificationCenter.default.addObserver(self, selector: #selector(self.reachabilityChanged), name: ReachabilityChangedNotification, object: reachability)

do{
    try reachability.startNotifier()
}
catch {
    print("could not start reachability notifier")
} 

Note : Add this below in your project's Bridging-Header file

注意:在您项目的 Bridging-Header 文件中添加以下内容

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: { 
NotificationCenter.default.addObserver(self, selector: #selector(self.reachabilityChanged), name: ReachabilityChangedNotification, object: reachability)

do{
    try reachability.startNotifier()
}
catch {
    print("could not start reachability notifier")
} 
.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 }

回答by Jayprakash Dubey

You can fetch IP address using the code below:

您可以使用以下代码获取 IP 地址:

Note : I've used reachability so that it captures new IP address in case WiFi is changed to another.

注意:我使用了可达性,以便在 WiFi 更改为另一个时它会捕获新的 IP 地址。

  1. In Podfilefile

    pod 'ReachabilitySwift'and then install pod

  2. In AppDelegate.swiftfile import ReachabilitySwift

    Note :If it prompts an error that Could not find ReachabilitySwift module then simply copy and paste this. It works!

  3. didFinishLaunchingOptionsfunction

    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: { 
    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.
        }
    
    .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 }
  4. Then copy paste below code in AppDelegatefile

    reachability.stopNotifier()  
    
    NSNotificationCenter.defaultCenter().removeObserver(self,name: ReachabilityChangedNotification,object: reachability)
    
  5. Add this in Bridging-Header file #include<ifaddrs.h>

    In case you don't have this file then you can create it Check this link

  1. Podfile文件中

    pod 'ReachabilitySwift'进而 install pod

  2. AppDelegate.swift文件中import ReachabilitySwift

    注意:如果提示无法找到 ReachabilitySwift 模块的错误,则只需复制并粘贴即可。有用!

  3. didFinishLaunchingOptions功能

    reachability.stopNotifier()  
    
    NSNotificationCenter.defaultCenter().removeObserver(self,name: ReachabilityChangedNotification,object: reachability)
    
  4. 然后将下面的代码复制粘贴到AppDelegate文件中

    func getIPAddress() -> String {
        var address: String = "error"
    
        var interfaces: ifaddrs? = nil
    
        var temp_addr: ifaddrs? = nil
        var success: Int = 0
        // retrieve the current interfaces - returns 0 on success
        success = getifaddrs(interfaces)
        if success == 0 {
            // Loop through linked list of interfaces
            temp_addr = interfaces
            while temp_addr != nil {
                if temp_addr?.ifa_addr?.sa_family == AF_INET {
                    // Check if interface is en0 which is the wifi connection on the iPhone
                    if (String(utf8String: temp_addr?.ifa_name) == "en0") {
                        // Get NSString from C String
                        address = String(utf8String: inet_ntoa((temp_addr?.ifa_addr as? sockaddr_in)?.sin_addr))
                    }
                }
                temp_addr = temp_addr?.ifa_next
            }
        }
            // Free memory
        freeifaddrs(interfaces)
        return address
    }
    
  5. 在 Bridging-Header 文件中添加这个 #include<ifaddrs.h>

    如果你没有这个文件,那么你可以创建它检查这个链接

6.

6.

func getIPAddressForCellOrWireless()-> String? {

    let WIFI_IF : [String] = ["en0"]
    let KNOWN_WIRED_IFS : [String] = ["en2", "en3", "en4"]
    let KNOWN_CELL_IFS : [String] = ["pdp_ip0","pdp_ip1","pdp_ip2","pdp_ip3"]

    var addresses : [String : String] = ["wireless":"",
                                         "wired":"",
                                         "cell":""]

    var address: String?
    var ifaddr: UnsafeMutablePointer<ifaddrs>? = nil
    if getifaddrs(&ifaddr) == 0 {

        var ptr = ifaddr
        while ptr != nil {
            defer { ptr = ptr?.pointee.ifa_next } // memory has been renamed to pointee in swift 3 so changed memory to pointee

            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)!), (WIFI_IF.contains(name) || KNOWN_WIRED_IFS.contains(name) || KNOWN_CELL_IFS.contains(name)) {

                    // String.fromCString() is deprecated in Swift 3. So use the following code inorder to get the exact IP Address.
                    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)
                    if WIFI_IF.contains(name){
                        addresses["wireless"] =  address
                    }else if KNOWN_WIRED_IFS.contains(name){
                        addresses["wired"] =  address
                    }else if KNOWN_CELL_IFS.contains(name){
                        addresses["cell"] =  address
                    }
                }

            }
        }
    }
    freeifaddrs(ifaddr)

    var ipAddressString : String?
    let wirelessString = addresses["wireless"]
    let wiredString = addresses["wired"]
    let cellString = addresses["cell"]
    if let wirelessString = wirelessString, wirelessString.count > 0{
        ipAddressString = wirelessString
    }else if let wiredString = wiredString, wiredString.count > 0{
        ipAddressString = wiredString
    }else if let cellString = cellString, cellString.count > 0{
        ipAddressString = cellString
    }
    return ipAddressString
}
  1. If you want to remove observer, then:

     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: { 
    if let addr = getWiFiAddress() {
       print(addr)
    } else {
       print("No WiFi address")
    }
    
    .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) { // **ipv6 committed if addrFamily == UInt8(AF_INET){ // 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 }
  1. 如果要删除观察者,则:

     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
        }
    

回答by BHAVIK PANCHAL

##代码##

回答by abhinavroy23

All the answers here gives only ip address for wifi and not wired or cellular. Following snippet can be used for wifi/wired/cellular case:

这里的所有答案仅提供 wifi 的 ip 地址,而不是有线或蜂窝网络。以下代码段可用于 wifi/有线/蜂窝案例:

##代码##

回答by niravdesai21

If you want only IPv4 response as output just modify the solution by Martin R.

如果您只想要 IPv4 响应作为输出,只需修改 Martin R 的解决方案。

##代码##

Usage:

用法:

##代码##

回答by Belboz Flathead

Swift 5 Cleanup

斯威夫特 5 清理

I updated an answer above to eliminate any force unwrapping and some SwiftLint cleanup.

我更新了上面的答案以消除任何强制解包和一些 SwiftLint 清理。

##代码##