Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/xcode/7.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Swift 如何使可选项在Xcode 9.4中可散列_Swift_Xcode_Optional - Fatal编程技术网

Swift 如何使可选项在Xcode 9.4中可散列

Swift 如何使可选项在Xcode 9.4中可散列,swift,xcode,optional,Swift,Xcode,Optional,在Xcode 10中,Swift编译器足够聪明,可以: 将包装可散列值的选项视为可散列 Xcode>=9.4还将处理包含所有可散列的structs 属性也是可散列的 奇怪的是,即使构建语言是Swift 4,甚至是Swift 3,Xcode 10也将optional视为可散列的 以以下代码为例: struct Foo: Hashable { var string1: String? var string2: String? } 该代码在Xcode 10下编译,并且使用Foo对象的

在Xcode 10中,Swift编译器足够聪明,可以:

  • 将包装
    可散列
    值的选项视为
    可散列

  • Xcode>=9.4还将处理包含所有可散列
    struct
    s 属性也是可散列的

  • 奇怪的是,即使构建语言是Swift 4,甚至是Swift 3,Xcode 10也将optional视为可散列的

    以以下代码为例:

    struct Foo: Hashable {
        var string1: String?
        var string2: String?
    }
    
    该代码在Xcode 10下编译,并且使用Foo对象的hashValue可以按预期工作,即使构建语言是Swift 3

    但是,在Xcode 9.4中,Foo结构不是自动可散列的,除非您将属性设置为非可选

    此代码按照您在Xcode 9.4/Swift 4.1中希望的方式编译和工作:

    struct Foo: Hashable {
        var string1: String
        var string2: String
    }
    
    如何在Xcode 9中使选项可散列?我当然可以自己为我的结构实现
    Hashable
    一致性,但是为多部分结构创建好的哈希实际上有点棘手,我不想为此担心


    我也想不出一个简单的方法来使可选的
    可散列
    。(同样,这只是XcodeSwift 4.2定义了
    作为

    特别是

    • .none
      与整数零具有相同的哈希值,与 类型,以及
    • 散列值
      .some(wrapped)
      通过混合
      与整数1包装在一起
    Swift 4.1(随Xcode 9.4提供)已经有了必要的工具来 实施类似的方法:

    • 条件一致性,即我们可以定义扩展

      extension Optional: Hashable where Wrapped: Hashable
      
    • 如果所有成员都是可哈希的,则类型的可哈希的自动合成

    下面是一个可能的实现:

    extension Optional: Hashable where Wrapped: Hashable {
        struct Combiner: Hashable {
            let left: Int
            let right: Wrapped
        }
    
        public var hashValue: Int {
            switch self {
            case .none:
                return 0.hashValue
            case .some(let wrapped):
                return Combiner(left: 1, right: wrapped).hashValue
            }
        }
    }
    
    例如:

    struct Foo: Hashable {
        var string1: String?
        var string2: String?
    }
    
    let foo = Foo(string1: "1", string2: "2")
    print(foo.hashValue) // 2171695307022640119
    
    要使此代码也能用Swift 4.2及更新版本编译,请 扩展方法可以有条件地编译(比较 ):


    您混淆了Xcode版本和Swift版本。即使使用Xcode 10,也可以使用Swift 3。我想你是在问如何在Swift 4.0或Swift 4.1而不是Swift 4.2中实现这一点?请不要将IDE版本与语言/编译器版本混淆,这是两个截然不同的概念。Swift也可以在Xcode之外编译(也许你应该试试这个来缩小你的问题范围),也可能是相关的(Swift 4.2),而且(Swift 4.2)我非常理解其中的区别。你可能认为语言版本会决定什么有效,什么无效,但我专门测试了它。它似乎是由编译器版本驱动的,而不是由您在IDE中选择的语言版本驱动的。在Xcode 10中,即使选择Swift 3作为语言版本,也会编译带有optionals的结构的版本,而在Xcode 9.4中它不会编译。在升级之前,请使用Sourcery的AutoHashable()。升级时,很容易将其删除并替换为隐式哈希表。我使用了“Xcode 10”和“Xcode 9.4”,因为我没有现成的权限访问这些IDE版本中包含的编译器版本的信息,它描述了我发现的情况。如果你有这方面的信息,这将是有益的。(我几乎总是在Xcode中使用LLVM Swift编译器,除非我正在使用brew构建项目,或者在Pi.EXTABLE上执行Swift。(投票)。这就是我要寻找的。但有一个问题:在可选的可哈希扩展的Swift 4.2版本中,在某些情况下,它将哈希值1和包装值的哈希值结合起来。(我假设这会使
    foo
    可选
    具有不同的哈希值。)您的版本不包含该步骤。不是吗?@duncac:它已经包含了,带有
    组合器(左:1,右:wrapped)。hashValue
    。哈希组合器函数不是公共函数,因此我使用了该“技巧”您可以检查
    foo.hashValue
    (foo-as-foo?).hashValue
    是否不同。-不客气,找到它很有趣!
    struct Foo: Hashable {
        var string1: String?
        var string2: String?
    }
    
    let foo = Foo(string1: "1", string2: "2")
    print(foo.hashValue) // 2171695307022640119
    
    #if swift(>=4.1.50) || (swift(>=3.4) && !swift(>=4.0))
    // Code targeting the Swift 4.2 compiler and above:
    // Conditional conformance `Optional: Hashable` defined in the standard library.
    #elseif swift(>=4.1) || (swift(>=3.3) && !swift(>=4.0))
    // Code targeting the Swift 4.1 compiler and above:
    
    extension Optional: Hashable where Wrapped: Hashable {
        // ...
    }
    
    #endif