'Modifying state during view update, this will cause undefined behavior.' error when typing on a textfield (SwiftUI)
This works for me, you don't even need to import Combine! When you use @Published
, SwiftUI will automatically synthesize the objectWillChange
subject, and will call send whenever the property is mutated. You can still call .send()
manually if you need to, but in most cases you won't.
class UserSettings: ObservableObject {
@Published var loggedIn : Bool = false
}
Excerpt from beta 5 release notes:
You can manually conform to ObservableObject by defining an objectWillChange publisher that emits before the object changes. However, by default, ObservableObject automatically synthesizes objectWillChange and emits before any @Published properties change.
This is the full code that is working fine for me (both iPhone Xr and real device, iPad 6th Gen):
window.rootViewController = UIHostingController(rootView: ContentView().environmentObject(UserSettings()))
import SwiftUI
struct ContentView: View {
var body: some View {
StartView()
}
}
class UserSettings: ObservableObject {
@Published var loggedIn : Bool = false
}
struct StartView: View {
@EnvironmentObject var settings: UserSettings
var body: some View {
if settings.loggedIn {
return AnyView(Text("LOGGED IN"))
} else {
return AnyView(LogInView())
}
}
}
struct LogInView: View {
@EnvironmentObject var settings: UserSettings
@State private var emailAddress: String = ""
@State private var password: String = ""
var body: some View {
GeometryReader { geometry in
VStack (alignment: .center){
HStack {
Image(systemName: "2.circle.fill")
.resizable()
.frame(width: 20, height: 20)
Text("Social App")
.font(.system(size: 12))
}.padding(.top, 30)
.padding(.bottom, 10)
Text("Log In to Your Account")
.font(.title)
.font(.system(size: 14, weight: .bold, design: Font.Design.default))
.padding(.bottom, 50)
TextField("Email", text: self.$emailAddress)
.frame(width: geometry.size.width - 45, height: 50)
.textContentType(.emailAddress)
.padding(EdgeInsets(top: 0, leading: 5, bottom: 0, trailing: 0))
.accentColor(.red)
.background(Color(red: 242 / 255, green: 242 / 255, blue: 242 / 255))
.cornerRadius(5)
TextField("Password", text: self.$password)
.frame(width: geometry.size.width - 45, height: 50)
.padding(EdgeInsets(top: 0, leading: 5, bottom: 0, trailing: 0))
.foregroundColor(.gray)
.background(Color(red: 242 / 255, green: 242 / 255, blue: 242 / 255))
.textContentType(.password)
.cornerRadius(5)
Button(action: {
self.settings.loggedIn = true
}) {
HStack {
Text("Log In")
}
.padding()
.frame(width: geometry.size.width - 40, height: 40)
.foregroundColor(Color.white)
.background(Color.blue)
.cornerRadius(5)
}
.padding(.bottom, 40)
Divider()
Button(action: {
print("Take to forget password VC")
}) {
Text("Forgot your password?")
}
Spacer()
}
.padding(.bottom, 90)
}
}
}