String.hashValue 在 Xcode 10 中构建时重置应用程序后不是唯一的
String.hashValue not unique after reset app when build in Xcode 10
我有一个 "get hash of string by String.hashValue
" 代码,我在下面添加了它。此代码在 Xcode 9.4.1.
中运行良好
工作良好意味着每当我关闭应用程序并重新打开它时,hashValue
的结果是相同的(唯一的)
private func cacheName(of url: String) -> String {
// The url is url of a png image, for example www.imageurl.com/image.png
return "\(url.hashValue)"
}
当我在 Xcode 10 中构建我的项目时,每次我重新启动应用程序(关闭并再次打开应用程序)时结果都会改变。 iOS、设备的版本,Swift版本相同。所以我认为问题是 Xcode 10 改变了一些影响 hashValue
的东西(也许在构建应用程序时配置??)
如果我使用 String.hash
代替,效果很好。但是在之前的版本中,我保存了hashValue
的结果,所以不想改了。
如何使 String.hashValue
的结果每次都唯一。或者任何建议将不胜感激
Swift 4.2 已经实现 SE-0206: Hashable Enhancements. This introduces a new Hasher struct that provides a randomly seeded hash function. That's why the hashing results differ everytime (since the seed is random). You can find the implementation of the Hasher struct, with the generation of a random seed, here.
如果你想要一个稳定的哈希值关联到字符串,跨设备和应用程序启动,你可以使用这个 solution by Warren Stringer:
let str = "Hello"
func strHash(_ str: String) -> UInt64 {
var result = UInt64 (5381)
let buf = [UInt8](str.utf8)
for b in buf {
result = 127 * (result & 0x00ffffffffffffff) + UInt64(b)
}
return result
}
strHash(str) //177798404835661
或者 these 在字符串上定义了几个扩展:
extension String {
var djb2hash: Int {
let unicodeScalars = self.unicodeScalars.map { [=11=].value }
return unicodeScalars.reduce(5381) {
([=11=] << 5) &+ [=11=] &+ Int()
}
}
var sdbmhash: Int {
let unicodeScalars = self.unicodeScalars.map { [=11=].value }
return unicodeScalars.reduce(0) {
(Int() &+ ([=11=] << 6) &+ ([=11=] << 16)).addingReportingOverflow(-[=11=]).partialValue
}
}
}
"Hello".djb2hash //210676686969
"Hello".sdbmhash //5142962386210502930
(这个是在Xcode10,Swift4.2上执行的)
我有一个 "get hash of string by String.hashValue
" 代码,我在下面添加了它。此代码在 Xcode 9.4.1.
工作良好意味着每当我关闭应用程序并重新打开它时,hashValue
的结果是相同的(唯一的)
private func cacheName(of url: String) -> String {
// The url is url of a png image, for example www.imageurl.com/image.png
return "\(url.hashValue)"
}
当我在 Xcode 10 中构建我的项目时,每次我重新启动应用程序(关闭并再次打开应用程序)时结果都会改变。 iOS、设备的版本,Swift版本相同。所以我认为问题是 Xcode 10 改变了一些影响 hashValue
的东西(也许在构建应用程序时配置??)
如果我使用 String.hash
代替,效果很好。但是在之前的版本中,我保存了hashValue
的结果,所以不想改了。
如何使 String.hashValue
的结果每次都唯一。或者任何建议将不胜感激
Swift 4.2 已经实现 SE-0206: Hashable Enhancements. This introduces a new Hasher struct that provides a randomly seeded hash function. That's why the hashing results differ everytime (since the seed is random). You can find the implementation of the Hasher struct, with the generation of a random seed, here.
如果你想要一个稳定的哈希值关联到字符串,跨设备和应用程序启动,你可以使用这个 solution by Warren Stringer:
let str = "Hello"
func strHash(_ str: String) -> UInt64 {
var result = UInt64 (5381)
let buf = [UInt8](str.utf8)
for b in buf {
result = 127 * (result & 0x00ffffffffffffff) + UInt64(b)
}
return result
}
strHash(str) //177798404835661
或者 these 在字符串上定义了几个扩展:
extension String {
var djb2hash: Int {
let unicodeScalars = self.unicodeScalars.map { [=11=].value }
return unicodeScalars.reduce(5381) {
([=11=] << 5) &+ [=11=] &+ Int()
}
}
var sdbmhash: Int {
let unicodeScalars = self.unicodeScalars.map { [=11=].value }
return unicodeScalars.reduce(0) {
(Int() &+ ([=11=] << 6) &+ ([=11=] << 16)).addingReportingOverflow(-[=11=]).partialValue
}
}
}
"Hello".djb2hash //210676686969
"Hello".sdbmhash //5142962386210502930
(这个是在Xcode10,Swift4.2上执行的)