SwiftUI中editMode变更无法传递至其他声明类的原因排查
问题原因
默认情况下,List组件会自动创建并维护一个专属的EditMode环境值,这个值和你在HomeView中通过@Environment(\.editMode)获取的并非同一个实例。你在HomeView里修改的是导航栈层级的editMode,而TitleList监听的是List内部的独立实例,两者互不关联,因此修改无法同步。
解决方案
在HomeView中手动创建一个共享的EditMode状态,通过environment(\.editMode:)方法传递给List,让HomeView和TitleList共享同一个editMode绑定。
修改步骤
- 将
HomeView中的@Environment(\.editMode)替换为@State变量,手动管理编辑状态:
// 替换原来的@Environment(\.editMode) @State private var editMode: EditMode = .inactive
- 给
List添加environment修饰符,注入共享的editMode绑定:
List { TitleList(titles: $titles) } .environment(\.editMode: $editMode) // 新增这一行
修改后的完整代码
import SwiftUI struct HomeView: View { @State private var editMode: EditMode = .inactive // 替换为@State @State private var sheetIsPresented = false @State private var titles: [String] = ["Title 1", "Title 2", "Title 3"] var body: some View { NavigationStack { VStack { List { TitleList(titles: $titles) } .environment(\.editMode: $editMode) // 注入共享的editMode .toolbar { ToolbarItem(placement: .navigationBarTrailing) { Button { editMode = .inactive // 直接修改状态,无需wrappedValue } label: { Label("Plus", systemImage: "plus") } } } } } .onChange(of: editMode) { _, _ in print("Worked") } } } struct TitleList: View { @Binding var titles: [String] @Environment(\.editMode) private var editMode @State private var isReordering = false var body: some View { ForEach(titles, id: \.self) { title in NavigationLink(destination: Text("Test")) { Text(title) } .moveDisabled(!isReordering) .swipeActions(allowsFullSwipe: false) { Button { editMode?.wrappedValue = .active isReordering = true } label: { Label("Reorder", systemImage: "list.bullet") } } .contentShape(Rectangle()) .highPriorityGesture( TapGesture().onEnded { if isReordering { withAnimation { editMode?.wrappedValue = .inactive } } }, isEnabled: isReordering ) } .onMove { source, destination in titles.move(fromOffsets: source, toOffset: destination) } .contentShape(Rectangle()) .onChange(of: editMode?.wrappedValue) { _, newValue in print("Test") if newValue == .inactive { isReordering = false } } } }
额外说明
- 现在
HomeView和TitleList使用同一个editMode实例,修改会双向同步。 - 你可以直接在
HomeView中修改editMode = .inactive,无需访问wrappedValue,因为它本身就是EditMode类型的@State变量。
内容的提问来源于stack exchange,提问作者Ser Pounce
相关产品推荐
相关产品推荐

