Categories
ios network-programming swift

Swift – Get device’s WIFI IP Address

84

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):

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?

    140

    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”.

    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 all running network interfaces. It can easily be modified to return only the IP address
    of the “en0” interface, and actually that is what I originally had
    answered at that thread (and this is just a Swift translation of the
    answer to how to get ip address of iphone programmatically):

    // 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:

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

    // 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
    }
    

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

    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: { $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 == 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
    }
    
    enum Network: String {
        case wifi = "en0"
        case cellular = "pdp_ip0"
        //... case ipv4 = "ipv4"
        //... case ipv6 = "ipv6"
    }
    

    Then we have access to the cellular IP as well.

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

    &

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

    32

    • @Martin R, C-style for statement is deprecated and will be removed in a future version of Swift. Can you fix it in your answer.

      Apr 15, 2016 at 8:46

    • @MartinR Thanks a ton, Man. 🙂

      Apr 15, 2016 at 8:53

    • 1

      @MartinR i created a bridging header file and then included #include <ifaddrs.h> in that file , and pasted your swift3 code in my viewcontroller but there are errors of getifaddrs() , ifaddrs , freeifaddrs , how to solve it ?

      Jan 4, 2017 at 8:56

    • 2

      @JayprakashDubey: This code is particular for the WiFi (“en0”) address. See stackoverflow.com/a/25627545/1187415 for code which retrieves the IP addresses of all running interfaces (and that worked with a cellular network in my test).

      – Martin R

      Mar 9, 2017 at 9:09


    • 1

      @MegaManX: fe80::10ec:6bd9:1d19:ac29%en0 is a “scoped literal IPv6 address“

      – Martin R

      Jun 5, 2018 at 11:29


    36

    To get IPAddress for wifi , wired, and cellular – 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 }
    
                guard let interface = ptr?.pointee else { return "" }
                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 ?? ""
    }
    

    How to use

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

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

    #include<ifaddrs.h>
    

    6

    • No errors, no warnings and works perfectly. Thanks for additional info in comments.

      – Sravan

      Sep 16, 2020 at 10:40

    • Welcome.. Happy coding

      Sep 16, 2020 at 13:11

    • Try once in simulator, i think i tested in real device.

      Dec 3, 2020 at 4:01

    • on device i m getting this kind of address 2409:4043:986:e121:6449:eae9:c78f:1042 is it correct???

      – shelen

      Dec 3, 2020 at 6:45

    • 1

      I didn’t have to include that inside my bridging header

      Dec 12, 2020 at 14:34

    19

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

    then write this method

    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
    }
    

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

    IP 🙁
    “10.0.0.94”
    )

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

    4

    • It returns array f addresses, how to get wifi address from there?

      Jun 10, 2015 at 6:23

    • u can easily access from array what u want..isn’t it?.

      – iAnurag

      Jun 10, 2015 at 6:24

    • “then write this method …” – That is what OP wrote in the question, your code is an exact copy (and also identical to the code posted here: stackoverflow.com/a/25627545/1187415).

      – Martin R

      Aug 25, 2016 at 7:11

    • Hi. i got crashed when trying to method UInt8(…), can someone help? stackoverflow.com/questions/55491986/…

      – famfamfam

      Apr 3, 2019 at 9:47