Swiftui Binding<String> 操作尝试每帧更新多次
Swiftui Binding<String> action tried to update multiple times per frame
我在调试文本字段输入问题时遇到问题。
信息:
-MacOs Monterey 版本 12.0 Beta 21A5284e
-Xcode 13.0 测试版 3 13A5192j
-物理 phone IOS 15.0 19A297e
问题说明:
当我尝试输入绑定到视图模型的文本字段时,出现错误:
Swiftui 绑定操作尝试每帧更新多次。
例如,当您尝试将数据发送到 firebase 时,这将导致数据丢失。
您看到的数据:
约翰
做
119203940
您实际得到的数据:
乔
D
119203
我使用的代码:
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")
}
}
}
}
功能部分有点无关紧要,因为一旦您开始键入,消息就会开始显示在控制台中。
为简单起见,我只是添加了一个只有一个文本字段且结果相同的新视图。
每当我将函数与@state 私有变量放在一起时,一切都很好。
我的期望
我希望将视图文本字段中填写的数据发送到 ViewModel 变量,以便我可以在函数中使用它来将数据发送到 firestore。
我是不是做错了什么,也许将另一个视图的值绑定到 ViewModel?我找不到关于此主题的任何内容或错误消息。
希望有人能告诉我在哪里看或接下来要检查什么。
你好,
这可能是您想要做的:
class UpdateProfileViewModel: ObservableObject {
@Published var voornaam: String = ""
@Published var achternaam: String = ""
@Published var telefoonnummer: String = ""
@Published 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")
}
}
}
}
struct FavoritesView: View {
@StateObject private var viewModel = UpdateProfileViewModel()
var body: some View {
VStack {
Text("Favorieten view")
TextField("Voornaam", text: $viewModel.voornaam)
}
}
}
我在调试文本字段输入问题时遇到问题。
信息:
-MacOs Monterey 版本 12.0 Beta 21A5284e
-Xcode 13.0 测试版 3 13A5192j
-物理 phone IOS 15.0 19A297e
问题说明: 当我尝试输入绑定到视图模型的文本字段时,出现错误: Swiftui 绑定操作尝试每帧更新多次。 例如,当您尝试将数据发送到 firebase 时,这将导致数据丢失。
您看到的数据:
约翰
做
119203940
您实际得到的数据:
乔
D
119203
我使用的代码:
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")
}
}
}
}
功能部分有点无关紧要,因为一旦您开始键入,消息就会开始显示在控制台中。 为简单起见,我只是添加了一个只有一个文本字段且结果相同的新视图。
每当我将函数与@state 私有变量放在一起时,一切都很好。
我的期望
我希望将视图文本字段中填写的数据发送到 ViewModel 变量,以便我可以在函数中使用它来将数据发送到 firestore。
我是不是做错了什么,也许将另一个视图的值绑定到 ViewModel?我找不到关于此主题的任何内容或错误消息。
希望有人能告诉我在哪里看或接下来要检查什么。
你好,
这可能是您想要做的:
class UpdateProfileViewModel: ObservableObject {
@Published var voornaam: String = ""
@Published var achternaam: String = ""
@Published var telefoonnummer: String = ""
@Published 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")
}
}
}
}
struct FavoritesView: View {
@StateObject private var viewModel = UpdateProfileViewModel()
var body: some View {
VStack {
Text("Favorieten view")
TextField("Voornaam", text: $viewModel.voornaam)
}
}
}