Swift的新手,所以请耐心等待。
我在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"
]
]
]
斯威夫特以下列方式抱怨它:
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 = [
^
我不明白。我的代码中没有_
。问题是我正在混合类型(字符串和数组)吗?
创建此结构的正确方法是什么?
答案 0 :(得分:2)
您猜测问题来自字典中的混合类型是绝对正确的。 ' _
'您所看到的是指未知的推断类型。 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使用Any
类型...
但你可能不应该这样做。如果您使用Any
,则会失去很多类型安全性。处理此问题的最佳方法是创建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]]
答案 1 :(得分:0)
这是创建此类数据结构的“正确”方法,但您应尝试通过指定所需类型或使用结构对其进行建模来使类型不那么模糊。
在游乐场中,类型被推断为[NSDictionary]
,但您应该使用像Swift这样的静态语言使用[[String : AnyObject]]
。
但这两种类型都不适用于REPL。因此,解决方法是使用[[String : Any]]
。这可能是因为它无法推断桥接标准类型。