我有以下枚举:
enum TaskKey: String{
case title = "title"
case completed = "completed"
case children = "children"
}
现在我使用这些键创建一个字典:
let taskDescriptions : Array<[TaskKey:Any]> = [
[ .title : "Buy milk",
.completed : false ],
[ .title : "Sleep",
.completed : false,
.children :
[
// `TaskKey` is required here
[ TaskKey.title : "Find a bed",
.completed : false
],
[ .title : "Wait",
.completed : false
]
] ],
[ .title : "Dance",
.completed : false ]
]
既然我的字典是
<[TaskKey:Any]>
类型的,我可以使用.title
而不是TaskKey.title
但是,对于嵌套了整个字典的.children
来说,我需要至少一个TaskKey.
引用,否则编译器会抱怨。对我来说这有点奇怪。我假设编译器在我像在示例中那样添加一个键时就隐式地将子项从
Any
键入soTaskKey:Any
。我不知道我的假设是否正确。为了美观起见,也可以对我的字典中的嵌套条目使用
.title
语法。 最佳答案
嵌套的子级是完全独立的。外部字典是[TaskKey:Any]
所以内部数组可以是任何类型。编译器需要一些关于.title
是什么的信息。当您使用TaskKey.title
将其中一个键显式化时,Swift将推断其余的键。
另一种方法是使用显式转换(as [[TaskKey:Any]]
或等效的as Array<[TaskKey:Any]>
)告诉Swift内部类型:
let taskDescriptions : Array<[TaskKey:Any]> = [
[ .title : "Buy milk",
.completed : false ],
[ .title : "Sleep",
.completed : false,
.children :
[
// `TaskKey` is required here
[ .title : "Find a bed",
.completed : false
],
[ .title : "Wait",
.completed : false
]
] as [[TaskKey:Any]] ],
[ .title : "Dance",
.completed : false ]
]
注意:通过显式地指定类型,使Swift编译器的工作变得容易,这将提高编译时间。
考虑使用
struct
或class
:我不确定字典是这里数据结构的最佳选择。您可能需要考虑使用
struct
或class
:class Task: CustomStringConvertible {
var title: String
var completed: Bool
var children: [Task]
var description: String { return "Task(title: \(title), completed: \(completed), children: \(children)" }
init(title: String, completed: Bool, children: [Task] = []) {
self.title = title
self.completed = completed
self.children = children
}
}
var taskDescriptions : [Task] = [
Task(title: "Buy milk",
completed: false
),
Task(title: "Sleep",
completed: false,
children:
[
Task(title: "Find a bed",
completed: false
),
Task(title: "Wait",
completed: false
)
]
),
Task(title: "Dance",
completed: false
)
]
这将比将
Any
转换为所需类型要容易得多。在这里使用
class
的优点是(相对于struct
)它使您能够轻松地更新内部任务:例如:
// Mark all of the children tasks of the second task as completed
for task in taskDescriptions[1].children {
task.completed = true
}