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

SwiftUI中输入单个字符后键盘自动收起问题求助

问题分析与解决方案

核心问题根源

键盘自动收起、输入会话错误的本质原因是ForEach使用了id: \.self。当你在TextField输入字符时,数组内的字符串元素值发生变化,ForEach会将其判定为全新元素,销毁原TextField并重建实例——这直接导致输入焦点丢失、键盘收起,同时触发输入会话相关的错误日志。

解决方案:改用带唯一标识的元素结构

通过创建带固定唯一ID的结构体,让ForEach基于稳定的ID追踪元素,而非依赖易变的字符串内容,就能解决焦点丢失问题。

1. 定义Identifiable结构体

创建遵循Identifiable协议的结构体,每个元素拥有唯一id和可编辑的text:

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

2. 调整状态变量

将原字符串数组替换为结构体数组,初始化时创建带空文本的元素:

@State var acts: [ActItem] = [ActItem(text: "")]
@State private var actcount = 1

3. 修改ForEach绑定逻辑

ForEach使用元素的id作为标识,绑定到act.text:

ForEach($acts) { $act in
    HStack{
        TextField("", text: $act.text)
    }
    .padding(12)
    .background(RoundedRectangle(cornerRadius: 15).foregroundStyle(.white))
    .overlay(RoundedRectangle(cornerRadius: 14)
        .stroke(Color.black, lineWidth: 2))
}

4. 调整添加/删除按钮逻辑

操作数组时,添加或移除ActItem实例:

// 添加按钮逻辑
self.acts.append(ActItem(text: ""))

// 删除按钮逻辑
acts.removeLast()

完整修改后的代码

import SwiftUI

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

struct ContentView: View {
    @State var acts: [ActItem] = [ActItem(text: "")]
    @State private var actcount = 1

    var body: some View {
        VStack(spacing: 16) {
            ForEach($acts) { $act in
                HStack{
                    TextField("", text: $act.text)
                }
                .padding(12)
                .background(RoundedRectangle(cornerRadius: 15).foregroundStyle(.white))
                .overlay(RoundedRectangle(cornerRadius: 14)
                    .stroke(Color.black, lineWidth: 2))
            }

            if actcount != 10 {
                if actcount == 1 {
                    Button{
                        self.acts.append(ActItem(text: ""))
                        self.actcount += 1
                    } label: {
                        Text("Add Act")
                            .frame(maxWidth: .infinity)
                            .padding(6)
                            .overlay(RoundedRectangle(cornerRadius: 12).stroke(Color.black, lineWidth: 2))
                    }
                } else {
                    HStack(spacing: 16){
                        Button{
                            self.acts.append(ActItem(text: ""))
                            actcount += 1
                        } label: {
                            Text("Add Act")
                                .frame(maxWidth: .infinity)
                                .padding(6)
                                .overlay(RoundedRectangle(cornerRadius: 12).stroke(Color.black, lineWidth: 2))
                        }
                        Button{
                            actcount -= 1
                            acts.removeLast()
                        } label: {
                            Text("Remove Act")
                                .frame(maxWidth: .infinity)
                                .padding(6)
                                .overlay(RoundedRectangle(cornerRadius: 12).stroke(Color.black, lineWidth: 2))
                        }
                    }
                }
            }
        }
        .padding()
    }
}

效果说明

修改后,TextField输入时仅更新对应元素的text值,ForEach通过固定id识别元素,不会重建TextField实例,焦点得以保持,键盘不再自动收起,RTI输入错误也会随之消失。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 12:25:11