Получите строку md5 в Swift 5 - PullRequest
7 голосов
/ 26 марта 2019

В Swift 4 мы могли бы использовать

var md5: String? {
    guard let data = self.data(using: .utf8) else { return nil }
    let hash = data.withUnsafeBytes { (bytes: UnsafePointer<Data>) -> [UInt8] in
        var hash: [UInt8] = [UInt8](repeating: 0, count: Int(CC_MD5_DIGEST_LENGTH))
        CC_MD5(bytes, CC_LONG(data.count), &hash)
        return hash
    }
    return hash.map { String(format: "%02x", $0) }.joined()
}

Но в Swift 5 withUnsafeBytes использует UnsafeRawBufferPointer вместо UnsafePointer. Как изменить функцию md5?

Ответы [ 2 ]

11 голосов
/ 26 марта 2019

Swift 5 версия: используйте UnsafeRawBufferPointer в качестве типа аргумента закрытия и bytes.baseAddress для передачи адреса в функцию Common Crypto:

extension String {
    var md5: String {
        let data = Data(self.utf8)
        let hash = data.withUnsafeBytes { (bytes: UnsafeRawBufferPointer) -> [UInt8] in
            var hash = [UInt8](repeating: 0, count: Int(CC_MD5_DIGEST_LENGTH))
            CC_MD5(bytes.baseAddress, CC_LONG(data.count), &hash)
            return hash
        }
        return hash.map { String(format: "%02x", $0) }.joined()
    }
}

(Обратите внимание, что преобразование строки в UTF-8 данные не могут потерпеть неудачу, нет необходимости возвращать необязательный.)

0 голосов
/ 02 апреля 2019

Эскимосский раствор

Ниже представлен вариант, основанный на решении, предложенном Eskimo из Apple в сообщении Swift Forum с путаницей в API данных UnsafeBytes :

extension String {
    func md5() -> String {
        let data = Data(utf8)
        var hash = [UInt8](repeating: 0, count: Int(CC_MD5_DIGEST_LENGTH))

        data.withUnsafeBytes { buffer in
            _ = CC_MD5(buffer.baseAddress, CC_LONG(buffer.count), &hash)
        }

        return hash.map { String(format: "%02hhx", $0) }.joined()
    }
}

Обратите внимание, что оно фактически совпадает с решением Мартина Р., но на строку короче (нет return hash).

Решение с использованием NSData

Это еще более короткое решение, использующее мостовое соединение с NSData.

extension String {
    func md5() -> String {
        let data = Data(utf8) as NSData
        var hash = [UInt8](repeating: 0, count: Int(CC_MD5_DIGEST_LENGTH))
        CC_MD5(data.bytes, CC_LONG(data.length), &hash)
        return hash.map { String(format: "%02hhx", $0) }.joined()
    }
}
...