代码之家  ›  专栏  ›  技术社区  ›  Andrew Hedges

错误:“_”不能转换为“StringLiteralConvertible”

  •  0
  • Andrew Hedges  · 技术社区  · 9 年前

    斯威夫特是个新手,所以请容忍我。

    我在REPL,尝试我认为的简单数据结构,如下:

    var stuff = [
        [
            "id" : "A9AD6748-62A1-47E9-B0F7-2CF9B9C138EE",
            "label" : "My Cool Label",
            "things" : [
                "1st string",
                "2nd string",
                "3rd string"
            ]
        ],
        [
            "id" : "9C7882A7-E40C-421F-BEDB-8C0249A768E3",
            "label" : "Another Cool Label",
            "things" : [
                "4th string",
                "5th string",
                "6th string"
            ]
        ]
    ]
    

    Swift以以下方式抱怨:

    repl.swift:72:13: error: '_' is not convertible to 'StringLiteralConvertible'
                "id" : "A9AD6748-62A1-47E9-B0F7-2CF9B9C138EE",
                ^~~~
    repl.swift:70:17: error: type of expression is ambiguous without more context
        var stuff = [
                    ^
    

    我不明白。没有 _ 在我的代码中。问题是我混合了类型(字符串和数组)吗?

    创建这种结构的正确方法是什么?

    2 回复  |  直到 9 年前
        1
  •  2
  •   porglezomp    9 年前

    你猜测问题来自于字典中的混合类型,这是绝对正确的。' _ '引用了未知的推断类型。Swift无法确定是哪种类型 stuff 在你的代码中,所以你必须让事情更清楚。 处理这个问题的快速而肮脏的方法是断言你的字典里有任何东西。

    > let x = ["one": 1, "two": "2"]
    repl.swift:7:27: error: '_' is not convertible to 'UnicodeScalarLiteralConvertible'
    > let x : [String: Any] = ["one": 1, "two": "2"]
    x: [String : Any] = 2 key/value pairs { ... }
    

    Swift不为你这样做的原因是Swift永远不会推断 Any 类型,并且有充分的理由。如果这样做的话,将不会出现大多数类型错误。所以你可以强迫Swift使用 任何 如果您想。。。

    但你可能不应该。如果您正在使用 任何 ,你在很多类型安全上都输了。处理此问题的最佳方法是创建 enum 以容纳所需的不同类型。这样,您可以将列表限制为仅包含您期望的内容。如果我们定义如下枚举:

    enum Thing {
        case AnInt(Int);
        case AString(String);
    }
    

    我们可以定义一个稍微更详细的列表,Swift将能够正确推断整个表达式的类型,并为我们提供更多的安全性。

    > let x = ["one": Thing.AnInt(1), "two": Thing.AString("2")]
    x: [String : Thing] = 2 key/value pairs { ... }
    

    您的示例可以使用如下枚举

    enum ListOrString {
        case AString(String);
        case AList([String]);
    }
    

    你可以这样写字典:

    var stuff = [
        [
            "id" : ListOrString.AString("A9AD6748-62A1-47E9-B0F7-2CF9B9C138EE"),
            "label" : .AString("My Cool Label"),
            "things" : .AList([
                "1st string",
                "2nd string",
                "3rd string"
            ])
        ],
        [
            "id" : .AString("9C7882A7-E40C-421F-BEDB-8C0249A768E3"),
            "label" : .AString("Another Cool Label"),
            "things" : .AList([
                "4th string",
                "5th string",
                "6th string"
            ])
        ]
    ]
    

    请注意,您只需指定 ListOrString 一次,每次你都可以用一个 . 。键入此项后,我的Swift REPL将正确推断类型为

    stuff: [[String : ListOrString]]
    
        2
  •  0
  •   Qbyte    9 年前

    这是创建这样的数据结构的“正确”方法,但您应该通过指定所需的类型或使用结构对其进行建模来尽量减少类型的模糊性。

    在操场上,该类型被推断为 [NSDictionary] 但你应该使用 [[String : AnyObject]] 在Swift这样的静态语言中。

    但这两种类型在REPL中都不起作用。作为解决方法,您可以使用 [[String : Any]] 。这可能是因为它无法推断桥接标准类型。