ios - 在 Xcode 10 中构建时重置应用程序后,String.hashValue 不唯一
问题描述
我有一个“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。这引入了一个新的 Hasher 结构,它提供了一个随机播种的散列函数。这就是为什么哈希结果每次都不同的原因(因为种子是随机的)。您可以在此处找到带有随机种子生成的 Hasher 结构的实现。
如果您想要一个与字符串关联的稳定哈希值,跨设备和应用程序启动,您可以使用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
或者在 String 上定义这几个扩展:
extension String {
var djb2hash: Int {
let unicodeScalars = self.unicodeScalars.map { $0.value }
return unicodeScalars.reduce(5381) {
($0 << 5) &+ $0 &+ Int($1)
}
}
var sdbmhash: Int {
let unicodeScalars = self.unicodeScalars.map { $0.value }
return unicodeScalars.reduce(0) {
(Int($1) &+ ($0 << 6) &+ ($0 << 16)).addingReportingOverflow(-$0).partialValue
}
}
}
"Hello".djb2hash //210676686969
"Hello".sdbmhash //5142962386210502930
(这是在 Xcode 10、Swift 4.2 上执行的)
推荐阅读
- laravel - 虚拟主机在 nginx ubuntu 18.04 中不起作用
- regex - 如何使用 Ruby gsub 和正则表达式进行部分字符串替换
- python - 如何从 mpts udp(一组带有 id 的程序)到带有一个程序 id(spts)的视频流
- javascript - 如何在javascript中将多个对象转换为键值对的数组[]
- javascript - 一旦评估为真,“删除”测试条件
- react-native - 在抽屉堆栈之间传递参数 react-navigation
- java - 如何从Java子目录中的类创建对象
- scala - 如何将 Flink DataSet 元组转换为一列
- c# - 在启动时设置 cookie (MVC .Net Core)
- java - 如何在相同的比较方法中也对名字进行排序