3

Let's say that I have a class Student

class Student: Identifiable, ObservableObject {
    var id = UUID()

    @Published var name = ""
}

Used within an Array in another class (called Class)

class Class: Identifiable, ObservableObject {
    var id = UUID()

    @Published var name = ""
    var students = [Student()]
}

Which is defined like this in my View.

@ObservedObject var newClass = Class()

My question is: how can I create a TextField for each Student and bind it with the name property properly (without getting errors)?

ForEach(self.newClass.students) { student in
    TextField("Name", text: student.name)
}

Right now, Xcode is throwing me this:

Cannot convert value of type 'TextField<Text>' to closure result type '_'

I've tried adding some $s before calling the variables, but it didn't seem to work.

João Gabriel
  • 73
  • 3
  • 9

1 Answers1

1

Simply change the @Published into a @State for the Student's name property. @State is the one that gives you a Binding with the $ prefix.

import SwiftUI

class Student: Identifiable, ObservableObject {
  var id = UUID()

  @State var name = ""
}

class Class: Identifiable, ObservableObject {
  var id = UUID()

  @Published var name = ""
  var students = [Student()]
}

struct ContentView: View {
  @ObservedObject var newClass = Class()

  var body: some View {
    Form {
      ForEach(self.newClass.students) { student in
        TextField("Name", text: student.$name) // note the $name here
      }
    }
  }
}

struct ContentView_Previews: PreviewProvider {
  static var previews: some View {
    ContentView()
  }
}

In general I'd also suggest to use structs instead of classes.

struct Student: Identifiable {
  var id = UUID()
  @State var name = ""
}

struct Class: Identifiable {
  var id = UUID()

  var name = ""
  var students = [
    Student(name: "Yo"),
    Student(name: "Ya"),
  ]
}

struct ContentView: View {
  @State private var newClass = Class()

  var body: some View {
    Form {
      ForEach(self.newClass.students) { student in
        TextField("Name", text: student.$name)
      }
    }
  }
}
Kevin Renskers
  • 5,156
  • 4
  • 47
  • 95
  • 2
    Xcode 13 gives me this warning about this: "Accessing State's value outside of being installed on a View. This will result in a constant Binding of the initial value and will not update." – Cocoanetics Oct 19 '21 at 08:03