代码之家  ›  专栏  ›  技术社区  ›  Quoc Nguyen Nofan Munawar

String.hashValue在Xcode 10中生成时重置应用程序后不唯一

  •  1
  • Quoc Nguyen Nofan Munawar  · 技术社区  · 6 年前

    我有一个“获取字符串哈希” String.hashValue “代码,我在下面添加了它。这段代码在xcode9.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)"
    }
    

    当我在xcode10中构建我的项目时,每次我重新启动应用程序(再次关闭并打开应用程序)结果都会发生变化。iOS、device、Swift版本相同。所以我认为问题是xcode10改变了一些影响 哈希值 (可能在生成应用程序时配置??)

    String.hash 相反,它工作得很好。但在以前的版本中,我保存了 哈希值

    String.hashValue 每次都独一无二。或任何建议都将不胜感激

    1 回复  |  直到 6 年前
        1
  •  18
  •   ielyamani    6 年前

    已实施Swift 4.2 SE-0206 随机播种 哈希函数。这就是哈希结果每次都不同的原因(因为种子是随机的)。你可以找到Hasher结构的实现,生成一个随机种子, here .

    如果您想要一个与字符串、accross设备和app lauches关联的稳定散列值,可以使用这个 solution 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 { $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
    

    (在代码10,Swift 4.2上执行)