我有以下枚举:
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
键入为TaskKey:Any
。
我想知道我的假设是否正确。同样,为了美观起见,也可以对字典中的嵌套条目使用.title
语法。
答案 0 :(得分:4)
嵌套的孩子是完全独立的。外部字典是[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
}