目录

单选

多选

多选示例

自定义数据类型的多选


单选

        为了实现单选我们需要提供一个绑定变量来指示选中的项,这个变量和列表项的类型是一致的,并且是可为空类型(apple语言的可选值类型——这个名称感觉怪怪的)。

        代码:

    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循环是无效的:

            List(selection: $selectedItem) {
                ForEach(items.indices, id: \.self) {
                    item in
                    Text(items[item])
                }
            }

        这就比较尴尬,如果要支持onMove、onDelete又必须使用ForEach,相当的不合理啊。

        另外,实测存在一个问题,内部判断选中项似乎是用文本来判断的,先点击“456”正常,在点击上面的“123”显示的选中项却是下面的“123”。

多选

        多选只能在编辑模式下使用,而编辑模式一般要和“Edit”按钮配合,“Edit”按钮是NavigationView的功能,所以必须用NavigationView包裹List:

NavigationView {
            List(){
                ......
            }
            .navigationBarItems(trailing: EditButton())
}

        实测这个编辑状态是整个NavigationView,也就是说,如果NavigationView下有多个List,任何一个List设置navigationBarItems(trailing: EditButton())都可以,而点击“Edit”按钮也会对所有List起作用:

        上图中两个List,一个设置了多选,一个设置了拖动和删除,点击“Edit”按钮两个都进入编辑状态。

多选示例

        多选需要不同的selection类型:

@State var selectedItems = Set<String>()

        除此而外并无区别。因为提供的是容器类型,所以不需要是可为空的类型。

        开启编辑模式的状态:

        此时可以通过单击来选择多项。

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

        通过观察selectedItems.count发现虽然两个“123”都显示为选中状态,但selectedItems.count=1。

        非编辑状态只能单选,选中“123”会导致两个“123”都显示为选中状态,但是可以再次单击取消另一个的选中状态。显然,这是混乱。

自定义数据类型的多选

        自定义数据类型要求比较高,下面的例子是可以编译的,但是并不能工作:

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协议。

        折腾了好久了没搞定,你知道怎么做吗?

更多推荐