问题描述
我尝试从用户那里获取(文本和颜色)并将它们添加到 SwiftUI 的列表中下面是应用程序的图像。要工作,我们应该为 PreAddTextField 提供绑定。感谢您的帮助 这是我的代码:
import SwiftUI
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: "",color: .purple)) })
vstack {
ScrollView {
ForEach(viewmodel.textItemsToAdd,id: \.id) { item in //note this is id:
\.id and not \.self
PreAddTextField(textInTextField: viewmodel.bindingForId(id: item.id),colorPickerColor: <#Binding<Color>#>)
}
}
}
.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 SwiftUIView_Previews: PreviewProvider {
static var previews: some View {
AddListView(showAddListView: .constant(false),appState: AppState())
}
}
struct PreAddTextField: View {
@Binding var textInTextField : String
@Binding var colorPickerColor : Color
var body: some View {
HStack {
TextField("Enter text",text: $textInTextField)
ColorPicker("",selection: $colorPickerColor)
}
}
}
struct Buttons: View {
@Binding var showAddListView : Bool
var save : () -> Void
var body: some View {
vstack {
HStack(spacing:100) {
Button(action: {
showAddListView = false}) {
Text("Cancel")
}
Button(action: {
showAddListView = false
// What should happen here to add Text to List???
save()
}) {
Text("Add")
}
}
}
.offset(y: 70)
}
}
struct Title: View {
var addItem : () -> Void
var body: some View {
vstack {
HStack {
Text("Add Text to list")
.font(.title2)
Spacer()
Button(action: {
addItem()
}) {
Image(systemName: "plus")
.font(.title2)
}
}
.padding()
Spacer()
}
}
}
数据模型:
import SwiftUI
struct Text1 : Identifiable,Hashable{
var id = UUID()
var text : String
var color : Color
}
class AppState : ObservableObject {
@Published var textData : [Text1] = [.init(text: "Item 1",color: .purple),.init(text: "Item 2",color: .purple)]
}
class AddListViewviewmodel : ObservableObject {
@Published var textItemsToAdd : [Text1] = [.init(text: "",color: .purple)] //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,color: .purple)
}
}
}
}
最后:
import SwiftUI
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
HStack {
Image(systemName: "square")
.foregroundColor(text.color)
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 ContentView_Previews: PreviewProvider {
static var previews: some View {
ListView()
}
}
解决方法
您可以为整个 Binding
项目创建一个 String
,而不是仅对 Binding
使用 Text1
:
class AddListViewViewModel : ObservableObject {
@Published var textItemsToAdd : [Text1] = [.init(text: "",color: .purple)]
func saveToAppState(appState: AppState) {
appState.textData.append(contentsOf: textItemsToAdd.filter { !$0.text.isEmpty })
}
func bindingForId(id: UUID) -> Binding<Text1> { //now returns a Text1
.init { () -> Text1 in
self.textItemsToAdd.first(where: { $0.id == id }) ?? Text1(text: "",color: .clear)
} set: { (newValue) in
self.textItemsToAdd = self.textItemsToAdd.map {
guard $0.id == id else {
return $0
}
return newValue
}
}
}
}
struct PreAddTextField: View {
@Binding var item : Text1
var body: some View {
HStack {
TextField("Enter text",text: $item.text) //gets the text property of the binding
ColorPicker("",selection: $item.color) //gets the color property
}
}
}
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: "",color: .purple)) })
VStack {
ScrollView {
ForEach(viewModel.textItemsToAdd,id: \.id) { item in
PreAddTextField(item: viewModel.bindingForId(id: item.id)) //parameter is changed here
}
}
}
.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)
}
}