如何在SwiftUI中将多个文本添加到列表中?(数据流)

如何在SwiftUI中将多个文本添加到列表中?(数据流),swiftui,swiftui-list,Swiftui,Swiftui List,我正试图通过swiftUI构建一个演示应用程序,从用户那里获取多个文本,并将它们添加到下面的列表中,每次用户按下加号按钮时,都会出现应用程序的图像。AddListView会显示给用户,用户可以在列表中添加多个文本。我无法通过新的switUI数据流将它们添加到列表中我不知道如何传递数据(我评论更多信息) 谢谢由于问题的多个项目部分,这就变得不那么琐碎了。但是,结合使用observateObjects和回调函数,这是完全可行的。请查看代码中的内联注释,以了解有关发生了什么的解释: struct Te

我正试图通过swiftUI构建一个演示应用程序,从用户那里获取多个文本,并将它们添加到下面的列表中,每次用户按下加号按钮时,都会出现应用程序的图像。AddListView会显示给用户,用户可以在列表中添加多个文本。我无法通过新的switUI数据流将它们添加到列表中我不知道如何传递数据(我评论更多信息)
谢谢由于问题的多个项目部分,这就变得不那么琐碎了。但是,结合使用
observateObject
s和回调函数,这是完全可行的。请查看代码中的内联注释,以了解有关发生了什么的解释:

struct Text1 : Identifiable , Hashable{
    var id = UUID()
    var text : String
}

//Store the items in an ObservableObject instead of just in @State
class AppState : ObservableObject {
    @Published var textData : [Text1] = [.init(text: "Item 1"),.init(text: "Item 2")]
}

//This view model stores data about all of the new items that are going to be added
class AddListViewViewModel : ObservableObject {
    @Published var textItemsToAdd : [Text1] = [.init(text: "")] //start with one empty item
    
    //save all of the new items -- don't save anything that is empty
    func saveToAppState(appState: AppState) {
        appState.textData.append(contentsOf: textItemsToAdd.filter { !$0.text.isEmpty })
    }
    
    //these Bindings get used for the TextFields -- they're attached to the item IDs
    func bindingForId(id: UUID) -> Binding<String> {
        .init { () -> String in
            self.textItemsToAdd.first(where: { $0.id == id })?.text ?? ""
        } set: { (newValue) in
            self.textItemsToAdd = self.textItemsToAdd.map {
                guard $0.id == id else {
                    return $0
                }
                return .init(id: id, text: newValue)
            }
        }
    }
}

struct AddListView: View {
    @Binding var showAddListView : Bool
    @ObservedObject var appState : AppState
    @StateObject private var viewModel = AddListViewViewModel()
    
    var body: some View {
        ZStack {
            Title(addItem: { viewModel.textItemsToAdd.append(.init(text: "")) })
            VStack {
                ScrollView {
                    ForEach(viewModel.textItemsToAdd, id: \.id) { item in //note this is id: \.id and not \.self
                        PreAddTextField(textInTextField: viewModel.bindingForId(id: item.id))
                    }
                }
            }
            .padding()
            .offset(y: 40)
            
            Buttons(showAddListView: $showAddListView, save: {
                viewModel.saveToAppState(appState: appState)
            })
            
        }
        .frame(width: 300, height: 200)
        .background(Color.white)
        .shadow(color: Color.black.opacity(0.3), radius: 10, x: 0, y: 10)
    }
}

struct PreAddTextField: View {
    @Binding var textInTextField : String //this takes a binding to the view model now
    
    var body: some View {
        VStack {
            TextField("Enter text", text: $textInTextField)
        }
    }
}

struct Buttons: View {
    @Binding var showAddListView : Bool
    var save : () -> Void //callback function for what happens when "Add" gets pressed
    var body: some View {
        VStack {
            HStack(spacing:100) {
                Button(action: {
                        showAddListView = false}) {
                    Text("Cancel")
                }
                Button(action: {
                    showAddListView = false
                    save()
                }) {
                    Text("Add")
                }
            }
        }
        .offset(y: 70)
    }
}

struct Title: View {
    
    var addItem : () -> Void //callback function for what happens when the plus button is hit
    
    var body: some View {
        VStack {
            HStack {
                Text("Add Text to list")
                    .font(.title2)
                Spacer()
                Button(action: {
                    addItem()
                }) {
                    Image(systemName: "plus")
                        .font(.title2)
                }
            }
            .padding()
            Spacer()
        }
    }
}

struct ListView: View {
    @StateObject var appState = AppState() //store the AppState here
    @State private var showAddListView = false
    
    var body: some View {
        NavigationView {
            VStack {
                ZStack {
                    List(appState.textData, id : \.self){ text in
                        Text(text.text)
                        
                    }
                    if showAddListView {
                        AddListView(showAddListView: $showAddListView, appState: appState)
                            .offset(y:-100)
                    }
                }
            }
            .navigationTitle("List")
            .navigationBarItems(trailing:
                                    Button(action: {showAddListView = true}) {
                                        Image(systemName: "plus")
                                            .font(.title2)
                                    }
            )
        }
    }
}

struct Text1:可识别、可散列{
var id=UUID()
变量文本:字符串
}
//将项目存储在ObserveObject中,而不是仅存储在@State中
类AppState:ObservableObject{
@已发布的变量textData:[Text1]=[.init(文本:“项目1”),.init(文本:“项目2”)]
}
//此视图模型存储有关将要添加的所有新项的数据
类AddListViewModel:ObserveObject{
@已发布的变量textItemsToAdd:[Text1]=[.init(文本:“”)]//从一个空项开始
//保存所有新项--不要保存任何空项
func saveToAppState(appState:appState){
appState.textData.append(contentsOf:textItemsToAdd.filter{!$0.text.isEmpty})
}
//这些绑定用于文本字段——它们附加到项目ID
func bindingForId(id:UUID)->Binding{
.init{()->中的字符串
self.textItemsToAdd.first(其中:{$0.id==id})?.text??“
}集合:{(newValue)在
self.textItemsToAdd=self.textItemsToAdd.map{
guard$0.id==id else{
返回$0
}
return.init(id:id,text:newValue)
}
}
}
}
结构AddListView:视图{
@绑定变量showAddListView:Bool
@ObservedObject变量appState:appState
@StateObject私有变量viewModel=addListViewModel()
var body:一些观点{
ZStack{
标题(addItem:{viewModel.textItemsToAdd.append(.init(文本:))})
VStack{
滚动视图{
ForEach(viewModel.textItemsToAdd,id:\.id){item in//注意这是id:\.id而不是\.self
PreAddTextField(textInTextField:viewModel.bindingForId(id:item.id))
}
}
}
.padding()
.偏移量(y:40)
按钮(showAddListView:$showAddListView,保存:{
viewModel.saveToAppState(appState:appState)
})
}
.框架(宽:300,高:200)
.背景(颜色.白色)
阴影(颜色:颜色。黑色。不透明度(0.3),半径:10,x:0,y:10)
}
}
结构PreAddTextField:视图{
@Binding var textinextfield:String//现在将绑定到视图模型
var body:一些观点{
VStack{
TextField(“输入文本”,text:$textInTextField)
}
}
}
结构按钮:视图{
@绑定变量showAddListView:Bool
var save:()->Void//回调函数,用于在按下“Add”时发生的情况
var body:一些观点{
VStack{
HStack(间距:100){
按钮(操作:{
showAddListView=false}){
文本(“取消”)
}
按钮(操作:{
showAddListView=false
保存()
}) {
文本(“添加”)
}
}
}
.偏移量(y:70)
}
}
结构标题:视图{
var addItem:()->Void//回调函数,用于在按下加号按钮时发生的情况
var body:一些观点{
VStack{
HStack{
文本(“将文本添加到列表”)
.font(.title2)
垫片()
按钮(操作:{
附加项()
}) {
图像(系统名称:“plus”)
.font(.title2)
}
}
.padding()
垫片()
}
}
}
结构列表视图:视图{
@StateObject var appState=appState()//将appState存储在此处
@状态私有变量showAddListView=false
var body:一些观点{
导航视图{
VStack{
ZStack{
列表(appState.textData,id:\.self){text in
Text(Text.Text)
}
如果显示AddListView{
AddListView(showAddListView:$showAddListView,appState:appState)
.偏移量(y:-100)
}
}
}
.navigationTitle(“列表”)
.navigationBarItems(尾部:
按钮(操作:{showAddListView=true}){
图像(系统名称:“plus”)
.font(.title2)
}
)
}
}
}

您的
Text1
数组在哪里?您的
AddListView
有点混乱。它有一个
ForEach
——你打算一次添加多个项目吗?它在名为textDataYes的数据模型中,你是对的,我想用户可以添加多个textfield,然后一次将它们添加到列表中。非常感谢,我真的很感激。我不知道如何感谢你