'init' недоступен: используйте 'withMemoryRebound (to: Capacity: _)' UnsafeMutablePointer - PullRequest
0 голосов
/ 15 января 2019

Я хочу использовать этот код Swift 2 в Swift 3 и 4:

func getLocalIP() -> String {
    var address = "error"
    var interfaces : UnsafeMutablePointer<ifaddrs>? = nil
    var temp_addr : UnsafeMutablePointer<ifaddrs>? = nil
    var success : Int32 = 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?.pointee.ifa_addr.pointee.sa_family == UInt8(AF_INET) {
                // Check if interface is en0 which is the wifi connection on the iPhone.
                if String(cString: (temp_addr?.pointee.ifa_name)!) == "en0" {
                    // Get NSString from C string.
                    address = String(cString: inet_ntoa(UnsafeMutablePointer<sockaddr_in>((temp_addr?.pointee.ifa_addr)!).pointee.sin_addr))
                }
            }
            temp_addr = temp_addr?.pointee.ifa_next
        }
    }
    // Free memory.
    freeifaddrs(interfaces)
    return address
}

Я получаю сообщение об ошибке UnsafeMutablePointer:

'init' недоступен: используйте 'withMemoryRebound (to: Capacity: _)'

1 Ответ

0 голосов
/ 15 января 2019

Текст ошибки говорит точно, что не так и что вы должны делать: вы не можете просто создать UnsafeMutablePointer, используя указатель на другой тип, и вы должны использовать .withMemoryRebound(to:Capacity:_) метод.

В вашем случае вы должны заменить

String(cString: inet_ntoa(UnsafeMutablePointer<sockaddr_in>((temp_addr?.pointee.ifa_addr)!).pointee.sin_addr))

с чем-то вроде этого:

temp_addr.pointee.ifa_addr.withMemoryRebound(to: sockaddr_in.self, capacity: 1, { sockaddr_ptr -> String? in
   guard let sin_addr = inet_ntoa(sockaddr_ptr.pointee.sin_addr) else { return nil }
   return String(cString: sin_addr)
})

Или вот полностью переписанная и улучшенная версия вашей функции:

enum LocalIPError: Error {
    case failedToRetrieveInterfaces(errorCode: Int32)
    case noEn0Address
}

func getLocalIP() throws -> String {
    // Retrieve the current interfaces - returns 0 on success.
    var interfaces : UnsafeMutablePointer<ifaddrs>? = nil
    let errorCode = getifaddrs(&interfaces)

    defer {
        // Free memory.
        freeifaddrs(interfaces)
    }

    guard
        errorCode == 0,
        let interfaceSequence = interfaces.flatMap({ first_addr in
            sequence(
                first: first_addr,
                next: { addr in addr.pointee.ifa_next }
            )
        })
        else { throw LocalIPError.failedToRetrieveInterfaces(errorCode: errorCode) }

    if let address = interfaceSequence.compactMap({ (temp_addr) -> String? in
        guard
            let ifa_addr = temp_addr.pointee.ifa_addr,
            ifa_addr.pointee.sa_family == sa_family_t(AF_INET),
            // Check if interface is en0 which is the wifi connection on the iPhone.
            String(cString: (temp_addr.pointee.ifa_name)) == "en0"
            else { return nil }

        return ifa_addr.withMemoryRebound(to: sockaddr_in.self, capacity: 1, { sockaddr_ptr -> String? in
            guard let sin_addr = inet_ntoa(sockaddr_ptr.pointee.sin_addr) else { return nil }
            return String(cString: sin_addr)
        })
    }).last {
        return address
    } else {
        throw LocalIPError.noEn0Address
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...