Reputation: 1080
StepsEntity is a core data entity
Receiving the following error when attempting to display a string value in a TextField: "Cannot convert value of type 'Published<[StepsEntity]>.Publisher' to expected argument type 'Binding'"
I know this is because StepsEntity in my core data model is @Published. @Published works great here as it allows all the data to be updated neatly. How can I display an @Published in a TextField?
Below is the piece where I am receiving the error:
List {
VStack(alignment: .center) {
if let recipeSteps = (vm.recipes[vm.getRecordsCount() - 1].steps?.allObjects as? [StepsEntity])?.sorted { $0.stepNumber < $1.stepNumber } {
if (textFieldCount == 1) {
//do nothing
} else if (textFieldCount > 1) {
ForEach(recipeSteps, id: \.stepNumber) { index in
HStack {
Text(String(index.stepNumber) + ".").bold()
TextField("", text: vm.$recipeSteps) //This is where the error is seen
}
}.onDelete(perform: { index in
self.vm.deleteRecipeSteps(at: index, from: vm.recipes[vm.getRecordsCount() - 1])
})
}
}
}
vm.recipeSteps refers to my CoreDataRelationshipViewModel, which is where all core data functions are handled. this is declared in the view struct as:
@StateObject var vm = CoreDataRelationshipViewModel()
Here is a snippet from the CoreDataRelationshipViewModel class:
class CoreDataRelationshipViewModel: ObservableObject {
let manager = CoreDataManager.instance
@Published var recipes: [RecipeEntity] = []
@Published var recipeSteps: [StepsEntity] = []
init() {
getRecipes()
}
func getRecipes() { ////more functions for retrieving, deleting, etc. in this section
I have tried converting the Published var to a binding but no luck:
TextField("", text: Binding(vm.$recipeSteps)!)
I have also tried referencing the recipeSteps declared in the if let statement within the list, but that does not work either.
I have been at it for a few days, and I think I have exhausted all options. Open to all ideas here. Maybe I need to rebuild my model?
Thoughts?
--Edits--
Upper portion of struct, where variables are created:
struct AddItemView: View {
@StateObject var viewModel = ViewModel()
@State var frameDimensions: CGFloat = 0
@State var imageButtonText: String = "Click To Add Image"
@State var imageToUpload: Data
@StateObject var vm = CoreDataRelationshipViewModel()
@Environment(\.presentationMode) var presentationMode
@State var stepInfo: String = ""
@State var textFieldCount: Int = 1
@State var stepNumber: [Int]
@State var recordsCount = 1
@State var errorText = ""
@State var stepErrorColor = Color.white.opacity(0)
@State var nameErrorColor = Color.white.opacity(0)
var body: some View {
ZStack {
HStack {
Upvotes: 0
Views: 4446
Reputation: 1080
I ended up restructuring the way my core data save works. Instead of saving item by item, I am now looping through a for in loop to save data all at the end. This allows me to display the data locally via some state variables, but then save the full array to my core data entity.
Upvotes: 0
Reputation: 1395
Your problem is that
TextField("", text: vm.$recipeSteps)
should actually be
TextField("", text: $vm.recipeSteps)
as you need to pass the view model with Binding rather than recipeSteps
(which, when using $
to pass it beyond vm
's dot accessor, passes a generic Publisher
).
Also, this would only work if the @Published
property in your view model conforms to StringProtocol
(is a string). Are you sure recipeSteps
is a string that can be edited via TextField
?
Upvotes: 6