【问题标题】:How can I show only selected items in SwiftUI List?如何仅显示 SwiftUI 列表中的选定项目?
【发布时间】:2020-04-17 16:35:00
【问题描述】:

如何让列表在 editMode 为 .inactive 时显示一组选定的项目,并在 editMode 为 .active 时显示所有可选选项,以便用户可以更改选定项目集?这是我尝试过的:

import SwiftUI

struct SelectionView: View {
    @Environment(\.editMode) var editMode
    @State var selectedItems = Set<String>(["1-item", "2-item", "3-item", "4-item"])
    let allItems = ["1-item", "2-item", "3-item", "4-item"]
    var items: [String] {
        if editMode?.wrappedValue == .inactive {
            return Array(selectedItems)
        }
        else {
            return allItems
        }
    }

    var body: some View {
        NavigationView {
            List(items, id: \.self, selection: $selectedItems) { item in
                Text(item)
            }
            .navigationBarItems(trailing: EditButton())
            .navigationBarTitle("Items")
        }
    }
}

选定的数组现在是无序的,因为它是从一个集合中生成的,我最终希望它以正确的顺序排列。但我首先尝试让列表按原样工作。

【问题讨论】:

    标签: ios swift list swiftui editmode


    【解决方案1】:

    这是对我有用的方法。不幸的是,由于List 内部(或错误)的细节,它并不完全好......

    想法是切换List的容器,根据选中的项目过滤其中一个,切换本身依赖于手动跟踪EditMode

    无论如何它都可以工作(使用 Xcode 11.2/iOS 13.2 测试,以及预览版)

    struct SelectionView: View {
        @State var editMode: EditMode = .inactive // ! Needed manual to track states
    
        @State var selectedItems = Set<String>(["1-item", "2-item", "3-item", "4-item"])
        let allItems = ["1-item", "2-item", "3-item", "4-item"]
        var items: [String] {
            allItems.filter { self.selectedItems.contains($0) }
        }
    
        @State var applyFilter = false
        var body: some View {
            NavigationView {
                VStack {
                    List(applyFilter ? items : allItems, id: \.self,
                         selection: $selectedItems) { item in
                            Text(item)
                    }
                    .navigationBarItems(trailing: EditButton())
                    .navigationBarTitle("Items")
                }
    //            .environment(\.editMode, $editMode) // << this is how it should be, but crash
                .environment(\.editMode, Binding<EditMode>(get: { self.editMode },
                   set: {
                        self.editMode = $0
    
                        // !!! below is needed workaround, because applying filter directly
                        // on close EditMode result in crash due to cached List internals
                        // until switch EditMode animation is finished completely
                        if $0 == .inactive {
                            DispatchQueue.main.asyncAfter(deadline: .now() + 0.2) {
                                self.applyFilter = true
                            }
                        } else {
                            self.applyFilter = false
                        }
                }))
            }
        }
    }
    

    【讨论】:

    • 用 selectedItems 过滤项目很好,但不得不使用 DispatchQueue 对我来说太老套了。希望有一个更清洁的解决方案。
    猜你喜欢
    • 2017-02-14
    • 2020-08-09
    • 2018-11-10
    • 1970-01-01
    • 1970-01-01
    • 2020-07-30
    • 2022-09-28
    • 1970-01-01
    • 2012-02-02
    相关资源
    最近更新 更多