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上执行的)