I'm new to iOS development. I am learning about MVVM. I am trying to hook up my app to firebase for authentication. It seems like everything is working because it's all building. BUT I force unwrapped the localized description error after I checked to see if it's not nil, and I do infact have an error message of "Password must be 6 characters or more." and the test password I'm setting up is more than 6 characters, so I think the problem is that the information is not being captured from the MainView to the Viewmodel...?
Please look at my code and let me know.
I currently have 3 files: SplashScreenView
import SwiftUI
struct SplashScreenView: View {
@State private var isActive = false
@State private var size = 0.7
@State private var opacity = 0.5
var body: some View {
if isActive {
withAnimation{
MainView().environmentObject(AuthViewModel())
}
} else {
ZStack {
RoundedRectangle(cornerRadius: 30, style: .continuous)
.foregroundStyle(LinearGradient(colors: [.orange, .red], startPoint: .topLeading, endPoint: .bottomTrailing))
.ignoresSafeArea()
VStack {
VStack{
Image("logo")
.resizable()
.scaledToFit()
.frame(width: 250)
}
.scaleEffect(size)
.opacity(opacity)
.onAppear(){
withAnimation(.easeIn(duration: 1.2)) {
self.size = 0.9
self.opacity = 1.0
}
}
}.onAppear() {
DispatchQueue.main.asyncAfter(deadline: .now() 2.5) {
self.isActive = true
}
}
}
}
}
}
struct SplashView_Previews: PreviewProvider {
static var previews: some View {
SplashScreenView()
}
}
MainView:
import SwiftUI
import Firebase
struct MainView: View {
@State var email = ""
@State var password = ""
@EnvironmentObject var authModel:AuthViewModel
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: 450)
.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: 40))
.offset(y:-10)
// Email TextField
TextField("", text: $email)
.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)
.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 {
authModel.register()
} label: {
Text("Sign Up")
.frame(width: 200, height: 40)
.background(
.orange
// RoundedRectangle(cornerRadius: 10, style: .continuous)
// .fill(.linearGradient(colors: [.red, .orange], startPoint: .topTrailing, endPoint: .bottomTrailing))
)
.cornerRadius(10)
.foregroundColor(.black)
.font(Font.custom("Poppins-Medium", size: 18))
}
Spacer()
Spacer()
// Login Link
HStack {
Text("Already Have An Account?")
.foregroundColor(.white)
.font(Font.custom("Poppins-Medium", size: 18))
Button {
authModel.login()
} label: {
Text("Login")
.foregroundColor(.orange)
.font(Font.custom("Poppins-Medium", size: 18))
}
}.offset(y: 100)
}
.frame(width: 350, height: 60)
}.ignoresSafeArea()
}
}
struct MainView_Previews: PreviewProvider {
static var previews: some View {
MainView().environmentObject(AuthViewModel())
}
}
extension View {
func placeholder<Content: View>(
when shouldShow: Bool,
alignment: Alignment = .leading,
@ViewBuilder placeholder: () -> Content) -> some View {
ZStack(alignment: alignment) {
placeholder().opacity(shouldShow ? 1 : 0)
self
}
}
}
and AuthViewModel:
import Foundation
import Firebase
class AuthViewModel: ObservableObject {
func register() {
Auth.auth().createUser(withEmail: MainView().email, password: MainView().password) { result, error in
if error != nil {
print(error!.localizedDescription)
}
}
}
func login() {
Auth.auth().signIn(withEmail: MainView().email, password: MainView().password) { result, error in
if error != nil {
print(error!.localizedDescription)
}
}
}
}
and for 'auth view model' before, I had had a @published var mainView = MainView()
but I don't think that's right...if someone can please explain what I'm doing wrong, I'd REALLY appreciate it!!! I did search on here, but the other similar questions to mine was in C# or another language.
CodePudding user response:
Every time you call MainView()
you are creating a different instance, of the view, one does not know about the other.
class AuthViewModel: ObservableObject {
func register(email: String, password: String) {
Auth.auth().createUser(withEmail: email, password: password) { result, error in
if error != nil {
print(error!.localizedDescription)
}
}
}
func login(email: String, password: String) {
Auth.auth().signIn(withEmail: email, password: password) { result, error in
if error != nil {
print(error!.localizedDescription)
}
}
}
}
Then use
authModel.register(email: email, password: password)
authModel.login(email: email, password: password)
Try the Apple SwiftUI Tutorials, if you don't focus on the basics you will face an uphill battle.