我在 SwiftUI 中有一个任务列表视图:
struct TaskListView: View {
@EnvironmentObject var listViewModel: ListViewModel
var body: some View {
ZStack {
if listViewModel.items.isEmpty {
Text("No items")
} else {
List {
ForEach(listViewModel.filteredItems){
item in ListRowView(item: item)
.onTapGesture {
withAnimation(.linear){
listViewModel.updateItem(item: item)
}
}
}
.onDelete(perform: listViewModel.deleteItem)
.onMove(perform: listViewModel.moveItem)
}.listStyle(.sidebar)
}
}
//.navigationTitle()
.navigationBarItems(
leading: EditButton(),
trailing: NavigationLink("Add", destination: AddView()))
}}
struct ListRowView: View {
let item: ItemModel
var body: some View {
HStack {
Image(systemName: item.isCompleted ? "checkmark.circle": "circle")
.foregroundColor(item.isCompleted ? .green: .red)
Text(item.title)
Spacer()
}.font(.body)//.title2)
.padding(.vertical,4)//8)
}}
具有以下视图模型:
class ListViewModel: ObservableObject {
@Published var items: [ItemModel] = [] {
didSet {
saveItems()
}
}
var filteredItems: [ItemModel] {
items.filter { $0.partOfDay.rawValue.contains("morning")}
}
let itemsKey: String = "items_list"
init() {
getItems()
}
func getItems() {
guard
let data = UserDefaults.standard.data(forKey: itemsKey),
let savedItems = try? JSONDecoder().decode([ItemModel].self, from: data)
else { return }
self.items = savedItems
}
func deleteItem(indexSet: IndexSet) {
items.remove(atOffsets: indexSet)
}
func moveItem(from: IndexSet, to: Int) {
items.move(fromOffsets: from, toOffset: to)
}
func addItem(title: String, partOfDay: PartOfDay) {
let newItem = ItemModel(title: title, partOfDay: partOfDay, isCompleted: false)
items.append(newItem)
}
func updateItem(item: ItemModel) {
if let index = items.firstIndex { (existingItem) -> Bool in
return existingItem.id == item.id
} {
items[index] = item.updateCompletion()
}
}
func saveItems() {
if let encodedData = try? JSONEncoder().encode(items) {
UserDefaults.standard.setValue(encodedData, forKey: itemsKey)
}
}}
我正在尝试对列表中已过滤的项目重新排序,但它不起作用 - 项目恢复到之前的顺序。如果我显示模型中的所有项目而不进行过滤(已发布的属性),则重新排序可以正常工作。如何重新排序已过滤的项目? (我的列表必须按白天的部分进行分组 - 早上、下午、晚上和晚上)
在 SwiftUI 中,最好您的类仅用于模型数据。对于视图数据,请使用
View
结构,即用于模型数据的各种视觉表示、排序、移动、过滤等。要过滤项目,您只需创建一个计算变量:
struct ItemsView: View {
@EnvironmentObejct var store: ModelStore
@State var searchTerm = "morning"
var filteredItems: [ItemModel] {
store.items.filter { item in
item.partOfDay.contains(searchTerm)
}
}
对于没有物品的情况,一个巧妙的技巧是
.overlay
,例如
List(filteredItems) { item in
...
}
.overlay {
if store.items.isEmpty {
Text("No items")
}
}