0

I'm trying to a build a notecard app, and currently I'm working on screen where the user can enter notecards. Everything works fine, except when I type in my term and definition for one notecard, it updates all other notecards so that they have the same term and definition. Thank you so much for any help, it is appreciated!:)

Here is a preview of my code

import SwiftUI

struct Notecard: Identifiable
{
    let id = UUID()
    let term2: String
    let def2: String
}
class Notecards: ObservableObject
{
   @Published var Notecardsarray = [Notecard]() //stores an array of the notecard items into a single object
}
struct ContentView: View{
    @ObservedObject var notecardobject = Notecards()
    @State private var term = "dfs"
    @State private var def = "df"

    var body: some View {
        NavigationView{
        List{
            ForEach(notecardobject.Notecardsarray){item in
                HStack{
                    TextField("enter term", text: self.$term)
                    TextField("enter definition", text: self.$def)
                }
            }
            .onDelete(perform: removeItems)
        }
    .navigationBarTitle("Notecards")
      .navigationBarItems(trailing:
          Button(action: {
            let newnotecard = Notecard(term2: self.term, def2: self.def)
              self.notecardobject.Notecardsarray.append(newnotecard)
          }) {
              Image(systemName: "plus")
          }
      )
        }

    }
   func removeItems(at offsets: IndexSet) {
       notecardobject.Notecardsarray.remove(atOffsets: offsets)
   }
}
//this will not actually be part of the app that goes to app store
struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

2 Answers2

0

I think the issue is, right here, you are passing the state variables self.$term and self.$def in which they are dfs and df. Instead, you should use item.term2 and item.def2 as it is in your ForEach

List{
    ForEach(notecardobject.Notecardsarray){item in
        HStack{
            TextField("enter term", text: self.$term)
            TextField("enter definition", text: self.$def)
        }
    }
    .onDelete(perform: removeItems)
}

Modified Code :

 List{
    ForEach(notecardobject.Notecardsarray){item in
        HStack{
            TextField("enter term", text: item.$term2)
            TextField("enter definition", text: item.$def2)
        }
    }
    .onDelete(perform: removeItems)
}

EDIT : I don't see the TextView struct in your examples, but if it requires a databinding, you will need to specify def2 and term2 as @State as well as make them var instead of let. Because they will now be sent to other views as a State, you will also need the $ that indicates a databinding. I made edits to the above code.

Modified code :

struct Notecard: Identifiable
{
    let id = UUID()
    @State var term2: String
    @State var def2: String
}
awrfisher
  • 196
  • 5
0

When you require a Binding in a ForEach loop, you need to loop through the indices rather than the elements.

Updated Notecard by making term2 and def2 mutable.

struct Notecard: Identifiable {
    let id = UUID()
    var term2: String
    var def2: String
}

Updated ContentView by changing the ForEach loop.

ForEach(notecardobject.Notecardsarray.indices, id: \.self){ index in
    HStack{
        TextField("enter term", text: self.$notecardobject.Notecardsarray[index].term2)
        TextField("enter definition", text: self.$notecardobject.Notecardsarray[index].def2)
    }
}
sfung3
  • 2,227
  • 1
  • 9
  • 30