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

SwiftUI中editMode变更无法传递至其他声明类的原因排查

问题原因

默认情况下,List组件会自动创建并维护一个专属的EditMode环境值,这个值和你在HomeView中通过@Environment(\.editMode)获取的并非同一个实例。你在HomeView里修改的是导航栈层级的editMode,而TitleList监听的是List内部的独立实例,两者互不关联,因此修改无法同步。

解决方案

在HomeView中手动创建一个共享的EditMode状态,通过environment(\.editMode:)方法传递给List,让HomeView和TitleList共享同一个editMode绑定。

修改步骤

  1. 将HomeView中的@Environment(\.editMode)替换为@State变量,手动管理编辑状态:
// 替换原来的@Environment(\.editMode)
@State private var editMode: EditMode = .inactive
  1. 给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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 06:03:14