I am having trouble debugging an issue with input from textfields.
Information:
-MacOs Monterey Version 12.0 Beta 21A5284e
-Xcode 13.0 beta 3 13A5192j
-Physical phone IOS 15.0 19A297e
Issue explanation: When i try to type in a textfield that is binded to a viewmodel i get the error: Swiftui Binding action tried to update multiple times per frame. This will result in data los when you try to send it to firebase for example.
Data you see:
Jhon
Do
119203940
The data you actually get back:
Jho
D
119203
Code that i use:
VIEW
import SwiftUI
import Firebase
import ImagePickerView
struct EditProfileView: View {
var storageManager = StorageManager()
@StateObject var UpdateProfileVM = UpdateProfileViewModel()
@State private var image = UIImage()
@State private var contentOffset = CGFloat(0)
@State private var showImagePicker: Bool = false
var body: some View {
ZStack(alignment: .top) {
TrackableScrollView(offsetChanged: { offsetPoint in
contentOffset = offsetPoint.y
}) {
content
}
VisualEffectBlur(blurStyle: .systemMaterial)
.opacity(contentOffset < -16 ? 1 : 0)
.ignoresSafeArea()
.frame(height: 0)
}
.background(Color("Background3").ignoresSafeArea(.all))
.frame(maxHeight: .infinity, alignment: .top)
.navigationTitle("Instellingen").font(.largeTitle)
}
var content: some View {
VStack(alignment: .leading, spacing: 16) {
Text("Pas je gegevens aan")
.font(.subheadline)
HStack {
CustomGreenIcon(icon: "person.circle")
.onChange(of: image, perform: { value in
storageManager.uploadProfile(image: image)
})
Text("Kies een foto")
.foregroundColor(Color.white)
.font(.subheadline)
}
.frame(maxWidth: .infinity, alignment: .leading)
.padding(10)
.background(Color("Accent"))
.cornerRadius(20)
.onTapGesture {
self.showImagePicker.toggle()
}
HStack {
CustomGreenIcon(icon: "character")
TextField("Voornaam", text: $UpdateProfileVM.voornaam)
.font(.subheadline)
}
.padding(10)
.background(Color("BackgroundFields"))
.cornerRadius(20)
HStack {
CustomGreenIcon(icon: "textformat")
TextField("Achternaam", text: $UpdateProfileVM.achternaam)
.font(.subheadline)
}
.padding(10)
.background(Color("BackgroundFields"))
.cornerRadius(20)
HStack {
CustomGreenIcon(icon: "iphone")
TextField("Telefoonnummer", text: $UpdateProfileVM.telefoonnummer)
.font(.subheadline)
}
.padding(10)
.background(Color("BackgroundFields"))
.cornerRadius(20)
GreenButton(text: "Bijwerken")
.onTapGesture {
UpdateProfileVM.UpdateProfile {
print("Met succes gedaan")
}
}
}
.frame(maxHeight: .infinity, alignment: .top)
.padding()
.sheet(isPresented: $showImagePicker) {
ImagePickerView(sourceType: .photoLibrary) { image in
self.image = image
}
}
}
}
struct EditProfileView_Previews: PreviewProvider {
static var previews: some View {
EditProfileView()
.environmentObject(UserStore())
// .environment(\.colorScheme, .dark)
}
}
ViewModel
import SwiftUI
import Firebase
class UpdateProfileViewModel: ObservableObject {
var voornaam: String = ""
var achternaam: String = ""
var telefoonnummer: String = ""
var alertMessage: String = ""
private var db = Firestore.firestore()
func UpdateProfile(completion: @escaping () -> Void) {
let userId = Auth.auth().currentUser?.uid ?? ""
let docRef = db.collection("gebruikers").document(userId)
docRef.updateData([
"Voornaam": voornaam,
"Achternaam": achternaam,
"Telefoonnummer": telefoonnummer
]) { error in
if let error = error {
print("Error updaten profiel: \(error)")
} else {
print("Profile updated")
}
}
}
}
The function part is kinda irrelevant since once you start typing the message will start showing in the console. For simplicity, i just added a new view with only one text field with the same result.
Whenever i put the function with @state private variables then everything is just fine.
My expectation
I expect the data that is filled in in the view textfield to be send to the ViewModel variable so that I can use it in a function to send data to firestore for example.
am I doing something wrong with maybe Binding the values from another view to the ViewModel? I cannot find anything on this topic or an error message.
Hope someone can tell me where to look or what to check next.
Greetings,
@Published
– Fraudulent