6

How to retrieve the device's IP address without using any third-party libraries using Swift 3 programming language? I have used the following code in order to get the IP address:

func getIPAddress() -> String? {
    var address : String?

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

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

            let interface = ptr.memory

            let addrFamily = interface.ifa_addr.memory.sa_family
            if addrFamily == UInt8(AF_INET) || addrFamily == UInt8(AF_INET6) {

                if let name = String.fromCString(interface.ifa_name) where name == "en0" {

                    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
 }

But the UnsafeMutablePointer<ifaddrs> syntax is not working. It throws a syntax error. Do I need to import a framework to try to help me?

  • That looks like the code in https://stackoverflow.com/a/30754194/1187415, which has been updated for Swift 3 some time ago. – Martin R Jun 14 '17 at 15:33
  • The question which is marked as original does not match this question. The "original" question just asks for wifi address. – Jonny Sep 10 '18 at 10:38

3 Answers3

19

I did following things in order to get the exact IP address of the device. Since I want to include the updated code to get IP address using Swift 3, I am posting the answer here. Referred from Swift - Get device's IP Address

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

  2. Create following function in order to get the IP Address.

    func getIP()-> 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 } // 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)!), name == "en0" {  // 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)
                }
    
            }
        }
        freeifaddrs(ifaddr)
      }
    
      return address
    }
    
  3. In order to get the IP Address, print(getIP())

For verification: -> Goto Settings -> Wi-Fi -> Click i symbol -> you can check your device IP Address.IP Address in my iPhone

OUTPUT SCREENSHOT: Output

Pancho
  • 4,099
  • 1
  • 21
  • 32
  • Good work...thanks... – DILIP KOSURI May 03 '18 at 05:11
  • This and a lot of other answers give me an IPv6 address, on an iPad Pro 2019 with iOS 12.2 connected to a local wifi network. anybody knows if the ifaddrs.h API has changed ? (my iPad wifi settings is showing me IPv4 addresses like your screenshots). – herme5 May 04 '19 at 17:05
  • 2
    @herme5 try to comment out `|| addrFamily == UInt8(AF_INET6)` – ioio007 May 24 '19 at 08:59
  • will it work on Simulator?? Currenlty not working on ioS 13.7 simulator – shelen Dec 02 '20 at 15:28
6

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

This is the framework needed to get IP address.

Also you can refer the following link:

Swift - Get device's IP Address

Arpit Jain
  • 1,660
  • 12
  • 23
  • it is no needed at all .. there are other possibilities how to obtain required information for all IP4 / IP6 addresses for all interfaces. see my answer. – user3441734 Jun 14 '17 at 15:14
2

try this (no bridging header is necessary, it works in Playground)

//: Playground - noun: a place where people can play

import Darwin

var temp = [CChar](repeating: 0, count: 255)
enum SocketType: Int32 {
    case  SOCK_STREAM = 0, SOCK_DGRAM, SOCK_RAW
}

// host name
gethostname(&temp, temp.count)
// create addrinfo based on hints
// if host name is nil or "" we can connect on localhost
// if host name is specified ( like "computer.domain" ... "My-MacBook.local" )
// than localhost is not aviable.
// if port is 0, bind will assign some free port for us

var port: UInt16 = 0
let hosts = ["localhost", String(cString: temp)]
var hints = addrinfo()
hints.ai_flags = 0
hints.ai_family = PF_UNSPEC

for host in hosts {
    print("\n\(host)")
    print()

    // retrieve the info
    // getaddrinfo will allocate the memory, we are responsible to free it!
    var info: UnsafeMutablePointer<addrinfo>?
    defer {
        if info != nil
        {
            freeaddrinfo(info)
        }
    }
    var status: Int32 = getaddrinfo(host, String(port), nil, &info)
    guard status == 0 else {
        print(errno, String(cString: gai_strerror(errno)))
        continue
    }
    var p = info
    var i = 0
    var ipFamily = ""
    var ipType = ""
    while p != nil {
        i += 1
        // use local copy of info
        var _info = p!.pointee
        p = _info.ai_next

        switch _info.ai_family {
        case PF_INET:
            _info.ai_addr.withMemoryRebound(to: sockaddr_in.self, capacity: 1, { p in
                inet_ntop(AF_INET, &p.pointee.sin_addr, &temp, socklen_t(temp.count))
                ipFamily = "IPv4"
            })
        case PF_INET6:
            _info.ai_addr.withMemoryRebound(to: sockaddr_in6.self, capacity: 1, { p in
                inet_ntop(AF_INET6, &p.pointee.sin6_addr, &temp, socklen_t(temp.count))
                ipFamily = "IPv6"
            })
        default:
            continue
        }
        print(i,"\(ipFamily)\t\(String(cString: temp))", SocketType(rawValue: _info.ai_socktype)!)

    }

}

it prints on my computer

localhost

1 IPv6  ::1 SOCK_RAW
2 IPv6  ::1 SOCK_DGRAM
3 IPv4  127.0.0.1 SOCK_RAW
4 IPv4  127.0.0.1 SOCK_DGRAM

Ivos-MacBook-Pro.local

1 IPv6  fe80::18a2:e892:fbd7:558e SOCK_RAW
2 IPv6  fe80::18a2:e892:fbd7:558e SOCK_DGRAM
3 IPv4  172.20.10.3 SOCK_RAW
4 IPv4  172.20.10.3 SOCK_DGRAM
user3441734
  • 16,722
  • 2
  • 40
  • 59
  • Nice, worked for me, pure Swift 3 – DwarDoh Aug 29 '17 at 20:06
  • Above on iOS 10 and simulator. Did not work on iPad 2, iOS 9. For IPv4 returns only localhost info 127.0.0.1, not device's, and this msg:"warning: could not execute support code to read Objective-C class data in the process. This may reduce the quality of type information available." – DwarDoh Aug 29 '17 at 20:16
  • Same problem on iPhone 6, iOS 10. no device IP's returned. Get this msg: "Warning: Libinfo call to mDNSResponder on main thread 0 Unknown error warning: could not execute support code to read Objective-C class data in the process. This may reduce the quality of type information available." – DwarDoh Aug 29 '17 at 20:22