SwiftUI中GridView结合CoreData无法删除条目,点击编辑无响应如何解决?
解决GridView结合CoreData无法删除条目的问题
问题原因
LazyVGrid不像List那样原生支持EditButton触发的编辑模式和onDelete回调,直接添加onDelete不会生效,点击编辑按钮自然也没有反应。
解决方案
需要手动管理编辑状态,为每个Grid项添加删除交互,具体修改步骤如下:
- 添加编辑状态变量
在HomeView中新增一个状态变量控制编辑模式的切换:
@State private var isEditing = false
- 替换默认EditButton
将工具栏里的EditButton换成自定义按钮,用来切换编辑状态:
ToolbarItem(placement: .topBarTrailing) { Button(isEditing ? "Done" : "Edit") { withAnimation { isEditing.toggle() } } .foregroundStyle(.black) }
- 为Grid项添加删除按钮
在每个Grid项的右上角叠加删除按钮,仅在编辑状态下显示:
ForEach(recipes) { recipe in NavigationLink { DetailView() } label: { // 原有item布局代码保持不变 } .overlay(alignment: .topTrailing) { if isEditing { Button { deleteRecipe(recipe) } label: { Circle() .fill(.red) .frame(width: 30, height: 30) .overlay( Image(systemName: "xmark") .foregroundColor(.white) .font(.caption) ) .padding(8) } } } } // 移除原有的.onDelete(perform: deleteRecipes),LazyVGrid不支持该回调
- 新增单个条目删除方法
添加针对单个Recipe对象的删除逻辑,替代原批量删除方法:
func deleteRecipe(_ recipe: Recipe) { moc.delete(recipe) try? moc.save() }
修改后的完整代码
struct HomeView: View { @Environment(\.managedObjectContext) var moc @FetchRequest(sortDescriptors: []) var recipes: FetchedResults<Recipe> @State private var isEditing = false let columns = [GridItem(.adaptive(minimum: 160))] var body: some View { NavigationStack { ScrollView { Text("\(recipes.count) \(recipes.count > 1 ? "recipes" : "recipe")") .font(.headline) .fontWeight(.medium) .frame(maxWidth: .infinity, alignment: .leading) .padding(.horizontal) LazyVGrid(columns: columns) { ForEach(recipes) { recipe in NavigationLink { DetailView() } label: { VStack { Image(.cake) .resizable() .aspectRatio(contentMode: .fill) StrokeText(text: recipe.name ?? "", width: 1.0, color: .black.opacity(0.80)) .font(.headline) .shadow(color: .black.opacity(0.5), radius: 0.0) .foregroundStyle(.white) .padding(.vertical, 10) .padding(.top, -10) .frame(maxWidth: 130) } .frame(width: 160, height: 220) .background(.white.opacity(0.50)) .clipShape(RoundedRectangle(cornerRadius: 20, style: .continuous)) .shadow(color: .gray.opacity(0.4), radius: 15) .padding(.vertical, 3) .overlay { RoundedRectangle(cornerRadius: 20) .stroke(.white, lineWidth: 1.7) .frame(width: 160, height: 220) } } .overlay(alignment: .topTrailing) { if isEditing { Button { deleteRecipe(recipe) } label: { Circle() .fill(.red) .frame(width: 30, height: 30) .overlay( Image(systemName: "xmark") .foregroundColor(.white) .font(.caption) ) .padding(8) } } } } } .padding([.bottom, .horizontal]) } .navigationTitle("My Recipes") .background(.cyan.opacity(0.3)) .toolbarBackground(.cyan.opacity(0.4), for: .navigationBar) .toolbar { ToolbarItem(placement: .topBarTrailing) { Button(isEditing ? "Done" : "Edit") { withAnimation { isEditing.toggle() } } .foregroundStyle(.black) } } } } func deleteRecipe(_ recipe: Recipe) { moc.delete(recipe) try? moc.save() } }
效果说明
点击工具栏的"Edit"按钮后,每个Grid项右上角会显示红色删除按钮,点击即可删除对应CoreData条目;点击"Done"按钮退出编辑模式。
内容的提问来源于stack exchange,提问作者burak
相关产品推荐
相关产品推荐

