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

SwiftUI:如何实现包含可编辑TextField的ForEach列表?

SwiftUI 电话号码列表组件优化方案

现有代码问题分析

  1. 数据模型错误使用@State:PhoneNumberListItem是数据结构体,@State仅用于SwiftUI视图内部的状态存储,放在模型里无法实现正确的双向绑定,也不能触发视图更新。
  2. 无法修改数组元素:listOfMyPhones是值类型数组,直接遍历元素无法修改phone值,因为ForEach拿到的是元素副本,修改不会同步回原数组。

修正后的代码实现

方案1:值类型数组 + 索引绑定(适合简单场景)

func ListOfMyPhoneNumbers() -> some View {
    @State var listOfMyPhones = [PhoneNumberListItem(name: "home", phone: "123")]
    
    return VStack {
        // 通过$绑定数组元素,实现双向修改
        ForEach($listOfMyPhones) { $item in
            TextField(item.name, text: $item.phone)
                .textFieldStyle(.roundedBorder)
        }
        
        Button("Add Phone") {
            listOfMyPhones.append(PhoneNumberListItem(name: "other", phone: ""))
        }
        .buttonStyle(.borderless)
        
        Spacer()
    }
    .padding()
}

struct PhoneNumberListItem: Identifiable {
    let id = UUID()
    var name: String // 改为var,方便未来扩展名称编辑功能
    var phone: String
}

方案2:ObservableObject(适合复杂场景,对应Compose的ViewModel)

如果未来需要处理验证、异步操作等复杂逻辑,推荐使用可观察对象:

class PhoneNumberListItem: ObservableObject, Identifiable {
    let id = UUID()
    var name: String
    @Published var phone: String // @Published对应Compose的mutableStateOf,修改时自动通知视图更新
    
    init(name: String, phone: String) {
        self.name = name
        self.phone = phone
    }
}

func ListOfMyPhoneNumbers() -> some View {
    @State var listOfMyPhones = [PhoneNumberListItem(name: "home", phone: "123")]
    
    return VStack {
        ForEach(listOfMyPhones) { item in
            @Bindable var bindableItem = item
            TextField(item.name, text: $bindableItem.phone)
                .textFieldStyle(.roundedBorder)
        }
        
        Button("Add Phone") {
            listOfMyPhones.append(PhoneNumberListItem(name: "other", phone: ""))
        }
        .buttonStyle(.borderless)
        
        Spacer()
    }
    .padding()
}

针对Android/Compose背景的适配说明

  • 状态管理对比:
    • Compose中你习惯用mutableStateOf修饰数据类属性,SwiftUI中值类型数组直接用@State数组+$绑定即可;引用类型则用ObservableObject+@Published,类似Compose里ViewModel结合StateFlow的用法。
    • @Bindable(SwiftUI 5.0+)对应Compose中对State对象的自动绑定,简化ObservableObject的双向绑定写法。
  • 未来扩展准备:
    把name设为var类型,后续添加名称TextField时,直接在ForEach里新增一个绑定$item.name的TextField即可,和Compose中添加TextField绑定状态的逻辑一致。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 13:15:25