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

SwiftUI中List组件的EditButton无法正常工作问题求助

问题解决:SwiftUI EditButton环境变量未更新的问题

问题根源

  1. 旧API兼容性问题:你使用的navigationBarItems在iOS 16及以上版本已被弃用,该API无法正确将EditButton的状态同步到@Environment(\.editMode)环境变量中。
  2. 视图层级缺失:如果LocationMasterListView没有被NavigationStack(iOS 16+)或NavigationView(iOS 15及以下)包裹,环境变量editMode无法被正确注入到视图中。

另外,ForEach的onDelete能正常工作是因为它直接绑定了List的内部编辑状态,不需要依赖环境变量editMode,所以即使环境变量未更新,删除按钮仍会显示。

修复方案

1. 替换为新的Toolbar API(iOS 16+)

将navigationBarItems替换为toolbar,用ToolbarItem添加按钮,确保editMode环境变量正确同步:

import SwiftUI

struct LocationMasterListView: View {
    @Environment(\.editMode) var editMode
    @Environment(\.managedObjectContext) private var viewContext
    @FetchRequest(sortDescriptors: [], animation: .default)
    private var locations: FetchedResults<Location>
    
    var body: some View {
        List {
            Text("Test")
            
            // 现在能正确响应编辑状态
            if editMode?.wrappedValue == .active {
                Text("is editing")
            } else {
                Text("not editing")
            }
            
            ForEach(locations) { location in
                NavigationLink(destination: LocationDetailView(location: location)) {
                    HStack {
                        MasterImageView(location: location)
                        VStack(alignment: .leading) {
                            Text(location.locationName)
                            Text(location.locationSuburb)
                                .font(.footnote)
                                .foregroundColor(.gray)
                        }
                    }
                }
            }.onDelete(perform: deleteLocation)
        }
        .navigationTitle("Favourite Places")
        // 使用新的Toolbar API
        .toolbar {
            ToolbarItem(placement: .navigationBarLeading) {
                EditButton()
            }
            ToolbarItem(placement: .navigationBarTrailing) {
                Button("+") {
                    addLocation()
                }
            }
        }
    }
    
    // 补充你已有的操作方法
    private func deleteLocation(offsets: IndexSet) {
        withAnimation {
            offsets.map { locations[$0] }.forEach(viewContext.delete)
            try? viewContext.save()
        }
    }
    
    private func addLocation() {
        let newLocation = Location(context: viewContext)
        newLocation.locationName = "New Place"
        newLocation.locationSuburb = "New Suburb"
        try? viewContext.save()
    }
}

2. 确保外层有导航容器

在调用LocationMasterListView的地方,用对应版本的导航容器包裹:

  • iOS 16+:使用NavigationStack
struct ContentView: View {
    var body: some View {
        NavigationStack {
            LocationMasterListView()
        }
    }
}
  • iOS 15及以下:使用NavigationView
struct ContentView: View {
    var body: some View {
        NavigationView {
            LocationMasterListView()
        }
    }
}

验证效果

修改后点击EditButton:

  • Text("Test")所在的列表项会显示编辑指示器(点击Edit后显示删除图标,或左滑出现删除按钮)
  • 判断editMode的文本会正确切换为"is editing"

内容的提问来源于stack exchange,提问作者user27341

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 19:08:13