So, I'm getting the following error:
SwiftUI/EnvironmentObject.swift:70: Fatal error: No ObservableObject of type AppViewModel found. A View.environmentObject(_:) for AppViewModel may be missing as an ancestor of this view.
However, I do actually in fact have .environmentObject(AppViewModel())
on every preview and I'm not sure why.
Here's the code in question:
import SwiftUI
struct SignUpView: View {
@State var email = ""
@State var password = ""
@EnvironmentObject var model:AppViewModel
var body: some View {
ZStack {
Color.theme.blue
RoundedRectangle(cornerRadius: 30, style: .continuous)
.foregroundStyle(LinearGradient(colors: [.orange, .red], startPoint: .topLeading, endPoint: .bottomTrailing))
.frame(width: 1000, height: 475)
.rotationEffect(.degrees(15))
.offset(x: 20)
VStack(spacing: 20) {
Image("logo")
.resizable()
.scaledToFill()
.frame(width: 100)
.offset(y: 10)
Text("Welcome")
.foregroundColor(.white)
.font(Font.custom("Poppins-Bold", size: 44))
Text("Please Sign Up")
.foregroundColor(Color.theme.blue)
.font(Font.custom("Poppins-Regular", size: 22))
.offset(y:-20)
// Email TextField
TextField("", text: $email)
.disableAutocorrection(true)
.autocapitalization(.none)
.foregroundColor(.white)
.textFieldStyle(.plain)
.placeholder(when: email.isEmpty) {
Text("Email Address")
.foregroundColor(.white)
.font(Font.custom("Poppins-Light", size: 20))
}
// Email TextBox
Rectangle()
.frame(width:350, height: 1)
.foregroundColor(.white)
.padding(.top, -5)
// Password TextField
SecureField("", text: $password)
.disableAutocorrection(true)
.autocapitalization(.none)
.foregroundColor(.white)
.textFieldStyle(.plain)
.placeholder(when: password.isEmpty) {
Text("Password")
.foregroundColor(.white)
.font(Font.custom("Poppins-Light", size: 20))
}
// Password TextBox
Rectangle()
.frame(width:350, height: 1)
.foregroundColor(.white)
.padding(.top, -5)
Button {
guard !email.isEmpty, !password.isEmpty else {
return
}
model.signUp(email: email, password: password)
} label: {
Text("Sign Up")
.frame(width: 200, height: 40)
.background(
Color.theme.blue
// RoundedRectangle(cornerRadius: 10, style: .continuous)
// .fill(.linearGradient(colors: [.red, .orange], startPoint: .topTrailing, endPoint: .bottomTrailing))
)
.cornerRadius(10)
.foregroundColor(.white)
.font(Font.custom("Poppins-Medium", size: 18))
}
Spacer()
// Login Link
HStack {
Text("Already Have An Account?")
.foregroundColor(.white)
.font(Font.custom("Poppins-Medium", size: 18))
NavigationLink("Login", destination: SignInView())
.foregroundColor(.orange)
.font(Font.custom("Poppins-Medium", size: 18))
}.offset(y: 100)
}
.frame(width: 350, height: 60)
}.ignoresSafeArea()
}
}
struct SignUpView_Previews: PreviewProvider {
static var previews: some View {
SignUpView().environmentObject(AppViewModel())
}
}
Here's my AppViewModel:
import Foundation
import Firebase
class AppViewModel: ObservableObject {
let auth = Auth.auth()
@Published var signedIn = false
var isSignedIn: Bool {
// If it does NOT equal nil, then this means it is TRUE that, YES, we are indeed signed in. Yay!
return auth.currentUser != nil
}
// If you want to pass information, you have to make placeholders for the variables to be passed in.
func signUp(email: String, password: String) {
auth.createUser(withEmail: email, password: password) { [weak self] result, error in
guard result != nil, error == nil else {
return
}
DispatchQueue.main.async {
// Successfully signed up
self?.signedIn = true
}
}
}
func login(email: String, password: String) {
auth.signIn(withEmail: email, password: password) { [weak self] result, error in
guard result != nil, error == nil else {
return
}
DispatchQueue.main.async {
// Successfully signed in
self?.signedIn = true
}
// if error != nil {
// print(error!.localizedDescription)
// }
}
}
func signOut() {
try? auth.signOut()
self.signedIn = false
}
}
Please let me know if I need to include more code...? Thanks in advance! (I'm a newbie.)
Figured it out for anyone interested...
NavigationLink("Login", destination: SignInView())
Needed to be changed to:
NavigationLink("Sign Up", destination: SignUpView().environmentObject(self.model))