据我所知,Swift标准库或Foundation框架都没有版本5 UUID的内置方法。
以下是一个可能的版本3和版本5 UUID实现,摘自生成v5 UUID。名称和命名空间是什么?的描述以及RFC 4122中的参考实现。
(已更新为Swift 4及更高版本。)
import Foundation
import CommonCrypto
extension UUID {
enum UUIDVersion: Int {
case v3 = 3
case v5 = 5
}
enum UUIDv5NameSpace: String {
case dns = "6ba7b810-9dad-11d1-80b4-00c04fd430c8"
case url = "6ba7b811-9dad-11d1-80b4-00c04fd430c8"
case oid = "6ba7b812-9dad-11d1-80b4-00c04fd430c8"
case x500 = "6ba7b814-9dad-11d1-80b4-00c04fd430c8"
}
init(version: UUIDVersion, name: String, nameSpace: UUIDv5NameSpace) {
var spaceUID = UUID(uuidString: nameSpace.rawValue)!.uuid
var data = withUnsafePointer(to: &spaceUID) { [count = MemoryLayout.size(ofValue: spaceUID)] in
Data(bytes: $0, count: count)
}
data.append(contentsOf: name.utf8)
var digest = [UInt8](repeating: 0, count:Int(CC_SHA1_DIGEST_LENGTH))
data.withUnsafeBytes { (ptr: UnsafeRawBufferPointer) -> Void in
switch version {
case .v3:
_ = CC_MD5(ptr.baseAddress, CC_LONG(data.count), &digest)
case .v5:
_ = CC_SHA1(ptr.baseAddress, CC_LONG(data.count), &digest)
}
}
digest[6] &= 0x0F
digest[6] |= UInt8(version.rawValue) << 4
digest[8] &= 0x3F
digest[8] |= 0x80
self = NSUUID(uuidBytes: digest) as UUID
}
}
示例1(您的情况):
let uuid = UUID(version: .v5, name: "5a23dbfb2626b400190998fc-5pCAvA7h8k9JuErRn", nameSpace: .dns)
print(uuid) // 2522B097-8532-548E-A18B-9366C6511B5E
例子2(来源于RFC 4122的附录B,经过勘误更正):
let uuid = UUID(version: .v3, name: "www.widgets.com", nameSpace: .dns)
print(uuid) //3D813CBB-47FB-32BA-91DF-831E1593AC29
initWithUUIDString:
和initWithUUIDBytes:
方法。现在的问题是,uuidv5(id1 + id2, uuidv5.DNS)
究竟是什么意思?请注意,在Swift 3+中,您应该使用UUID
而不是提供相同方法的NSUUID
(init(uuidString:)
)。 - Larme