SwiftUI中按expireDate排序后用ForEach展示视图的实现方法
按过期日期排序CardData数组并展示的实现方法
核心思路
通过创建计算属性生成按expireDate排序后的数组,既不修改原数组的存储顺序,又能实现排序展示;同时通过元素的id匹配原数组绑定,保证编辑功能正常。
具体实现步骤
1. 添加排序后的计算属性
在CardView结构体内部添加只读计算属性,根据需求选择升序(最近过期的卡片在前)或降序(最远过期的卡片在前):
// 升序:最近过期的卡片排在最前面 var sortedDatas: [CardData] { datas.sorted { $0.expireDate < $1.expireDate } } // 可选:降序:最远过期的卡片排在最前面 // var sortedDatas: [CardData] { // datas.sorted { $0.expireDate > $1.expireDate } // }
2. 修改ForEach绑定逻辑
遍历排序后的数组,通过元素id匹配原数组索引获取绑定对象,确保后续编辑功能不受影响:
List { ForEach(sortedDatas) { card in if let index = datas.firstIndex(where: { $0.id == card.id }) { NavigationLink(destination: DetailView(cardData: $datas[index])){ CardDataView(cardData: card) } .listRowBackground(card.theme.mainColor) } } .onDelete(perform: deleteItems) }
3. (可选)直接修改原数组顺序
如果不需要保留原始添加顺序,可以在onAppear中直接对原数组排序:
.onAppear { DispatchQueue.main.asyncAfter(deadline: .now() + 2) { launchScreenManager.dismiss() } // 升序排序原数组 datas.sort { $0.expireDate < $1.expireDate } }
这种方式更简洁,但会改变原数组的存储顺序。
完整修改后的CardView代码
import SwiftUI struct CardView: View { @Binding var datas: [CardData] @Environment(\.scenePhase) private var scenePhase @State private var isPresentingNewCardView = false @State private var newCardData = CardData.Data() let saveAction: () -> Void @EnvironmentObject var launchScreenManager: LaunchScreenManager @State private var confirmationShow = false // 排序后的计算属性 var sortedDatas: [CardData] { datas.sorted { $0.expireDate < $1.expireDate } } var body: some View { List { ForEach(sortedDatas) { card in if let index = datas.firstIndex(where: { $0.id == card.id }) { NavigationLink(destination: DetailView(cardData: $datas[index])){ CardDataView(cardData: card) } .listRowBackground(card.theme.mainColor) } } .onDelete(perform: deleteItems) } .navigationTitle("Expiry Date") .navigationBarTitleDisplayMode(.inline) .toolbar { Button(action: { isPresentingNewCardView = true }) { Image(systemName: "plus") } .accessibilityLabel("New data") } .sheet(isPresented: $isPresentingNewCardView) { NavigationView { DetailEditView(data: $newCardData) .toolbar { ToolbarItem(placement: .cancellationAction) { Button("Dismiss") { isPresentingNewCardView = false newCardData = CardData.Data() } } ToolbarItem(placement: .confirmationAction) { Button("Add") { let newData = CardData(data: newCardData) datas.append(newData) isPresentingNewCardView = false newCardData = CardData.Data() } } } } } .onChange(of: scenePhase) { phase in if phase == .inactive { saveAction() } } .onAppear { DispatchQueue.main.asyncAfter(deadline: .now() + 2) { launchScreenManager.dismiss() } } } func deleteItems(at offsets: IndexSet) { datas.remove(atOffsets: offsets) } }
内容的提问来源于stack exchange,提问作者Felixsi chung
相关产品推荐
相关产品推荐

