You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SwiftUI中GridView结合CoreData无法删除条目,点击编辑无响应如何解决?

解决GridView结合CoreData无法删除条目的问题

问题原因

LazyVGrid不像List那样原生支持EditButton触发的编辑模式和onDelete回调,直接添加onDelete不会生效,点击编辑按钮自然也没有反应。

解决方案

需要手动管理编辑状态,为每个Grid项添加删除交互,具体修改步骤如下:

  1. 添加编辑状态变量
    在HomeView中新增一个状态变量控制编辑模式的切换:
@State private var isEditing = false
  1. 替换默认EditButton
    将工具栏里的EditButton换成自定义按钮,用来切换编辑状态:
ToolbarItem(placement: .topBarTrailing) {
    Button(isEditing ? "Done" : "Edit") {
        withAnimation {
            isEditing.toggle()
        }
    }
    .foregroundStyle(.black)
}
  1. 为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不支持该回调
  1. 新增单个条目删除方法
    添加针对单个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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 00:19:53