
目录
单选
为了实现单选我们需要提供一个绑定变量来指示选中的项,这个变量和列表项的类型是一致的,并且是可为空类型(apple语言的可选值类型------这个名称感觉怪怪的)。
代码:
Swift
var items: [String] = ["123", "456", "123"] //数据
@State private var selectedItem: String? //选中项
//in view
Text(" \(selectedItem != nil ? selectedItem! : "no selection")")
List(items, id: \.self, selection: $selectedItem) {
item in
Text(item)
}
没有选中的时候:

有选中的时候:

如果写成ForEach循环是无效的:
Swift
List(selection: $selectedItem) {
ForEach(items.indices, id: \.self) {
item in
Text(items[item])
}
}
这就比较尴尬,如果要支持onMove、onDelete又必须使用ForEach,相当的不合理啊。
另外,实测存在一个问题,内部判断选中项似乎是用文本来判断的,先点击"456"正常,在点击上面的"123"显示的选中项却是下面的"123"。
多选
NavigationView和编辑模式
多选只能在编辑模式下使用,而编辑模式一般要和"Edit"按钮配合,"Edit"按钮是NavigationView的功能,所以必须用NavigationView包裹List:
Swift
NavigationView {
List(){
......
}
.navigationBarItems(trailing: EditButton())
}
实测这个编辑状态是整个NavigationView,也就是说,如果NavigationView下有多个List,任何一个List设置navigationBarItems(trailing: EditButton())都可以,而点击"Edit"按钮也会对所有List起作用:

上图中两个List,一个设置了多选,一个设置了拖动和删除,点击"Edit"按钮两个都进入编辑状态。
多选示例
多选需要不同的selection类型:
Swift
@State var selectedItems = Set<String>()
除此而外并无区别。因为提供的是容器类型,所以不需要是可为空的类型。
开启编辑模式的状态:

此时可以通过单击来选择多项。
注意,前面已经知道单选是根据字符串内容来判断的,存在显示错误的选中项的问题。现在多选呢,则是选择任何一个"123"都会导致两个"123"显示为选中状态:

通过观察selectedItems.count发现虽然两个"123"都显示为选中状态,但selectedItems.count=1。
非编辑状态只能单选,选中"123"会导致两个"123"都显示为选中状态,但是可以再次单击取消另一个的选中状态。显然,这是混乱。
自定义数据类型的多选
自定义数据类型要求比较高,下面的例子是可以编译的,但是并不能工作:
Swift
struct Data: Identifiable, Hashable {
var id: UUID = UUID()
var i: Int
var name: String
func hash(into hasher: inout Hasher) {
hasher.combine(id)
}
}
@State var datas: [Data] = [
Data(i: 1, name: "magnifyingglass"), Data(i: 2, name: "globe.americas"),
Data(i: 3, name: "sun.rain.circle"),
]
@State var mySelectedItems = Set<Data>()
NavigationView {
List(datas, selection: $mySelectedItems) {
item in
Text(item.name)
}.navigationBarItems(trailing: EditButton())
}
自定义类型必须支持Hashable协议。
折腾了好久了没搞定,你知道怎么做吗?