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

SwiftUI中ForEach嵌套UITextView拖拽后文本丢失问题求助

问题原因

你当前用数组索引作为ForEach的id,拖拽排序时SwiftUI会根据索引重用视图。原绑定旧索引的TestEditor会被分配给新数组元素,但TestEditor里的@State var i不会自动更新,且makeUIView仅在视图初始化时设置一次文本,导致拖拽后编辑器显示旧元素文本,看起来像是丢失输入内容。

解决方案

1. 给Blocks模型添加唯一标识

让Blocks遵循Identifiable协议,确保每个元素有唯一标识,让ForEach能正确跟踪元素:

struct Blocks: Identifiable {
    let id = UUID()
    var text: String
}

2. 修改ContentView的遍历逻辑

直接遍历数组元素,用绑定传递单个元素,替代索引遍历:

struct ContentView: View {
    @StateObject var myList = ListBlocks()

    func move(from source: IndexSet, to destination: Int) {
        myList.list.move(fromOffsets: source, toOffset: destination)
    }

    var body: some View {
        List {
            ForEach($myList.list) { $block in
                WrapTest(block: $block)
            }
            .onMove(perform: move)
        }
    }
}

3. 更新WrapTest视图

接收单个元素的绑定,不再传递整个ListBlocks和索引:

struct WrapTest: View {
    @Binding var block: Blocks

    var body: some View {
        TestEditor(block: $block)
    }
}

4. 重构TestEditor

直接用元素绑定同步文本,移除索引依赖,优化UITextView更新逻辑:

struct TestEditor: UIViewRepresentable {
    @Binding var block: Blocks

    func makeUIView(context: Context) -> UITextView {
        let textView = UITextView()
        textView.delegate = context.coordinator
        textView.text = block.text
        return textView
    }

    func updateUIView(_ uiView: UITextView, context: Context) {
        // 仅当文本不一致时更新,避免输入时被视图更新覆盖内容
        if uiView.text != block.text {
            uiView.text = block.text
        }
    }

    func makeCoordinator() -> Coordinator {
        Coordinator(self)
    }

    class Coordinator: NSObject, UITextViewDelegate {
        var parent: TestEditor

        init(_ parent: TestEditor) {
            self.parent = parent
        }

        func textViewDidChange(_ textView: UITextView) {
            // 实时同步输入文本到绑定的元素
            parent.block.text = textView.text
        }
    }
}

核心改进说明

  • 用Identifiable元素的唯一id替代索引作为ForEach标识,确保拖拽后视图与元素正确关联,避免错误重用。
  • 通过@Binding直接绑定单个Blocks元素,彻底消除索引变化带来的同步问题。
  • 在updateUIView中添加文本判断,防止SwiftUI视图更新干扰用户输入。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 23:55:25