使用Swift 3获取iPhone或iPad设备的IP地址

6
如何在不使用任何第三方库的情况下,使用Swift 3编程语言获取设备的IP地址?我已经使用了以下代码来获取IP地址:
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
 }

但是UnsafeMutablePointer<ifaddrs>语法不起作用,会抛出语法错误。我需要引入一个框架来帮助我吗?


那看起来像是 https://dev59.com/9V0a5IYBdhLWcg3wD1Hb#30754194 中的代码,该代码已经在一段时间前更新为 Swift 3。 - Martin R
被标记为原始的问题与此问题不匹配。 "原始"问题只是询问wifi地址。 - Jonny
3个回答

19

为了获取设备的精确IP地址,我采取了以下步骤。由于我想使用Swift 3更新代码来获取IP地址,因此在此发布答案。引用自Swift - Get device's IP Address

  1. 在桥接头文件中添加#include<ifaddrs.h>

  2. 创建以下函数以获取IP地址。

    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. 为了获取IP地址,print(getIP())

验证: -> 进入设置 -> Wi-Fi -> 点击i符号 -> 您可以检查您的设备IP地址。IP Address in my iPhone

输出屏幕截图: Output


干得好...谢谢... - DILIP KOSURI
这个和很多其他答案给了我一个IPv6地址,在连接到本地wifi网络的iPad Pro 2019上使用iOS 12.2。有人知道ifaddrs.h API是否已更改吗?(我的iPad wifi设置向我显示像您的截图一样的IPv4地址)。 - herme5
2
@herme5 尝试将 || addrFamily == UInt8(AF_INET6) 注释掉。 - ioio007
它能在模拟器上运行吗?目前在iOS 13.7模拟器上无法工作。 - shelen

6

在你的桥接头文件中添加 #include<ifaddrs.h>

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

另外,您可以参考以下链接:

Swift - 获取设备的 IP 地址


不需要这样做...有其他方法可以获取所有接口的所有IP4 / IP6地址所需的信息。请查看我的回答。 - user3441734

2

尝试这个(不需要桥接头,在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)!)

    }

}

它在我的电脑上打印

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

不错,对我有用,纯Swift 3。 - DwarDoh
以上代码在iOS 10及模拟器上运行良好,但在iPad 2,iOS 9上无法正常工作。对于IPv4仅返回本地主机信息127.0.0.1,而非设备的IP地址,并且会出现以下警告消息:“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
iPhone 6,iOS 10上出现相同的问题,没有返回设备IP。收到此消息:“Warning:在主线程上对mDNSResponder进行Libinfo调用 0未知错误 警告:无法执行支持代码以读取进程中的Objective-C类数据。这可能会降低可用的类型信息的质量。” - DwarDoh

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接