Ios 如何仅显示SwiftUI列表中的选定项目?
当editMode为.inactive时,如何使列表显示一组选定项目,当editMode为.inactive时,如何使列表显示所有可选选项,以便用户可以更改选定项目集?以下是我尝试过的:Ios 如何仅显示SwiftUI列表中的选定项目?,ios,swift,list,swiftui,editmode,Ios,Swift,List,Swiftui,Editmode,当editMode为.inactive时,如何使列表显示一组选定项目,当editMode为.inactive时,如何使列表显示所有可选选项,以便用户可以更改选定项目集?以下是我尝试过的: import SwiftUI struct SelectionView: View { @Environment(\.editMode) var editMode @State var selectedItems = Set<String>(["1-item", "2-item",
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")
}
}
}
导入快捷界面
结构选择视图:视图{
@环境(\.editMode)变量editMode
@状态变量selectedItems=Set([“1项”、“2项”、“3项”、“4项”])
让allItems=[“1项”、“2项”、“3项”、“4项”]
变量项:[字符串]{
如果editMode?.wrappedValue==.inactive{
返回数组(selectedItems)
}
否则{
返回allItems
}
}
var body:一些观点{
导航视图{
列表(项目,id:\.self,选择:$selectedItems){item in
文本(项目)
}
.navigationBarItems(尾部:EditButton())
.navigationBarTitle(“项目”)
}
}
}
所选数组现在是无序的,因为它是从集合生成的,我最终希望它的顺序正确。但我首先尝试让列表按原样工作。以下是它对我的工作方式。不幸的是,由于
List
internal(或bug)的细节,它不是完全好的
其思想是切换列表的容器
根据所选项目过滤其中一个容器,切换本身取决于手动跟踪编辑模式
无论如何,它都可以工作(使用Xcode 11.2/iOS 13.2进行测试,并在预览中进行测试)
struct SelectionView:View{
@状态变量editMode:editMode=.inactive/!需要手动跟踪状态
@状态变量selectedItems=Set([“1项”、“2项”、“3项”、“4项”])
让allItems=[“1项”、“2项”、“3项”、“4项”]
变量项:[字符串]{
allItems.filter{self.selectedItems.contains($0)}
}
@状态变量applyFilter=false
var body:一些观点{
导航视图{
VStack{
列表(applyFilter?项目:allItems,id:\.self,
选择:$selectedItems){中的项
文本(项目)
}
.navigationBarItems(尾部:EditButton())
.navigationBarTitle(“项目”)
}
//.environment(\.editMode,$editMode)//使用selectedItems筛选项目很好,但是使用DispatchQueue对我来说太麻烦了。希望有一个更干净的解决方案。
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
}
}))
}
}
}