iOS开发 SwiftUI 7:List 单选多选

目录

单选

多选

NavigationView和编辑模式

多选示例

自定义数据类型的多选


单选

为了实现单选我们需要提供一个绑定变量来指示选中的项,这个变量和列表项的类型是一致的,并且是可为空类型(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"。

多选

多选只能在编辑模式下使用,而编辑模式一般要和"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协议。

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