Hey y'all,
I have an error that is causing my app to crash on line 366:
Thread 1: Fatal error: Unexpectedly found nil while unwrapping an Optional value
My file:
import SwiftUI
import Firebase
struct LoginView: View {
@AppStorage("log_Status") var status = false
@StateObject var model = ModelData()
var body: some View {
ZStack {
if status {
VStack(spacing: 25) {
OnboardingView()
Button(action: {
model.logOut()
}, label: {
Text("Sign Out")
.foregroundColor(Color.secondary)
.font(.headline)
})
}
} else {
LogView(model: model)
}
}
}
}
struct LoginView_Previews: PreviewProvider {
static var previews: some View {
LoginView()
}
}
struct LogView: View {
@ObservedObject var model : ModelData
var body: some View {
ZStack {
VStack {
Spacer(minLength: 0)
ZStack {
if UIScreen.main.bounds.height < 750 {
SignInImage()
} else {
SignInImage()
}
}
.padding(.horizontal)
.padding(.vertical, 20)
.background(Color.white.opacity(0.2))
.cornerRadius(30)
VStack(spacing: 4) {
HStack(spacing: 0){
Text("Food = ")
.font(.system(size: 35))
.foregroundColor(Color.white)
.fontWeight(.semibold)
Text("Life.")
.font(.system(size: 35))
.foregroundColor(Color.white)
.fontWeight(.bold)
}
Text("Let order some deliciousness!")
}
.padding(.top)
VStack(spacing: 20){
CustomTextField(image: "envelope", placeHolder: "Email", txt: $model.email)
CustomTextField(image: "lock", placeHolder: "Password", txt: $model.password)
}
.padding(.top)
Button(action: {
model.login()
}, label: {
Text("Login")
.fontWeight(.bold).foregroundColor(Color("Blue")) .padding(.vertical) .frame(width: UIScreen.main.bounds.width - 30)
.background(Color.white) .clipShape(Capsule())
})
HStack(spacing: 12){
Text("Don't have an account?") .foregroundColor(Color.white.opacity(0.7))
Button(action: {model.isSignUp.toggle()}) {
Text("Sign Up Now") .fontWeight(.bold) .foregroundColor(.white) } } .padding(.top,25)
.padding(.bottom, 1)
Button(action: {
model.resetPassword()
}) {
Text("Forget Password?") .fontWeight(.bold) .foregroundColor(.white)
}
.padding(.top, 20)
Divider()
Spacer(minLength: 0)
}
if model.isLoading {
LoadingView()
}
}
.background(LinearGradient(gradient: Gradient(colors: [Color("Blue"), Color("Purple")]), startPoint: .top, endPoint: .bottom))
.ignoresSafeArea(.all, edges: .all)
.fullScreenCover(isPresented: $model.isSignUp){
SignUpView(model: model)
}
.alert(isPresented: $model.alert, content: {
Alert(title: Text("Message"), message: Text(model.alertMsg), dismissButton: .destructive(Text("Ok")))
})
}
}
struct SignUpView: View {
@ObservedObject var model: ModelData
var body: some View {
ZStack(alignment: Alignment(horizontal: .trailing, vertical: .top)) {
VStack {
Spacer(minLength: 0)
ZStack {
if UIScreen.main.bounds.height < 750 {
SignInImage()
} else {
SignInImage()
}
}
.padding(.horizontal)
.padding(.vertical, 20)
.background(Color.white.opacity(0.2))
.cornerRadius(30)
VStack(spacing: 4) {
HStack(spacing: 0){
Text("New ")
.font(.system(size: 35))
.foregroundColor(Color.white)
.fontWeight(.semibold)
Text("Account")
.font(.system(size: 35))
.foregroundColor(Color.white)
.fontWeight(.bold)
}
Text("Create An Account!")
}
.padding(.top)
VStack(spacing: 20){
CustomTextField(image: "envelope", placeHolder: "Email", txt: $model.email_SignUp)
CustomTextField(image: "lock", placeHolder: "Password", txt: $model.password_SignUp)
CustomTextField(image: "lock", placeHolder: "Re - Enter Password", txt: $model.reEnterPassword)
}
.padding(.top)
Button(action: {
model.signUp()
}, label: {
Text("Sign Up")
.fontWeight(.bold).foregroundColor(Color("Blue")) .padding(.vertical) .frame(width: UIScreen.main.bounds.width - 30)
.background(Color.white) .clipShape(Capsule())
})
Spacer(minLength: 0)
}
Button(action: {
model.isSignUp.toggle()
}, label: {
Image(systemName: "xmark")
.padding()
.foregroundColor(.white)
.background(Color.black.opacity(0.6)).clipShape(Circle())
})
.padding(.trailing)
.padding(.top, 10)
if model.isLoading {
LoadingView()
}
}
.background(LinearGradient(gradient: Gradient(colors: [Color("Blue"), Color("Purple")]), startPoint: .top, endPoint: .bottom))
.ignoresSafeArea(.all, edges: .all)
.alert(isPresented: $model.alert, content: { Alert(title: Text("Message"), message: Text(model.alertMsg), dismissButton: .destructive(Text("Ok"), action: {
if model.alertMsg == "Email verification has been sent. Verify your email."
{ model.isSignUp.toggle()
model.email_SignUp = ""
model.password_SignUp = ""
model.reEnterPassword = ""
}
}))
})
}
}
struct CustomTextField : View {
var image : String
var placeHolder : String
@Binding var txt : String
var body: some View{
ZStack(alignment: Alignment(horizontal: .leading, vertical: .center)) {
Image(systemName: image) .font(.system(size: 24)) .foregroundColor(Color("Purple")) .frame(width: 60, height: 60) .background(Color.white) .clipShape(Circle())
ZStack{
if placeHolder == "Password" || placeHolder == "Re - Enter Password"{ SecureField(placeHolder, text: $txt) } else{
TextField(placeHolder, text: $txt) } } .padding(.horizontal) .padding(.leading,65) .frame(height: 60) .background(Color.white.opacity(0.2)) .clipShape(Capsule()) } .padding(.horizontal) } }
class ModelData: ObservableObject {
@Published var email = ""
@Published var password = ""
@Published var isSignUp = false
@Published var email_SignUp = ""
@Published var password_SignUp = ""
@Published var reEnterPassword = ""
@Published var isLinkSend = false
@Published var alert = false
@Published var alertMsg = ""
@Published var isLoading = false
@AppStorage("log_Status") var status = false
func resetPassword() {
let alert = UIAlertController(title: "Reset Your Password", message: "Enter your email to reset your password.", preferredStyle: .alert)
alert.addTextField { (password) in
password.placeholder = "Email"
}
let proceed = UIAlertAction(title: "Reset", style: .default) { (_) in
if alert.textFields![0].text! != ""{ withAnimation{
self.isLoading.toggle()
}
Auth.auth().sendPasswordReset(withEmail: alert.textFields![0].text!) { (err) in
withAnimation{
self.isLoading.toggle()
}
if err != nil {
self.alertMsg = err!.localizedDescription
self.alert.toggle()
return
}
self.alertMsg = "Password reset link has been sent."
self.alert.toggle()
}
}
}
let cancel = UIAlertAction(title: "Cancel", style: .destructive, handler: nil)
alert.addAction(cancel)
alert.addAction(proceed)
UIApplication.shared.windows.first?.rootViewController?.present(alert, animated: true)
}
func login() {
if email == "" || password == ""{
self.alertMsg = "Fill in the contents properly."
self.alert.toggle()
return
}
withAnimation {
self.isLoading.toggle()
}
Auth.auth().signIn(withEmail: email, password: password) { (result, err) in
withAnimation {
self.isLoading.toggle()
}
if err != nil {
self.alertMsg = err!.localizedDescription
self.alert.toggle()
return
}
}
let user = Auth.auth().currentUser
if !user!.isEmailVerified {
self.alertMsg = "Please verify your email."
self.alert.toggle()
try! Auth.auth().signOut()
return
withAnimation() {
self.status = true
}
}
}
func signUp() {
if email_SignUp == "" || password_SignUp == "" || reEnterPassword == "" {
self.alertMsg = "Fill the contentss properly."
self.alert.toggle()
return
}
if password_SignUp != reEnterPassword {
self.alertMsg = "The password is not matching."
self.alert.toggle()
return
}
withAnimation{
self.isLoading.toggle()
}
Auth.auth().createUser(withEmail: email_SignUp, password: password_SignUp) { (result, err) in
withAnimation {
self.isLoading.toggle()
}
if err != nil {
self.alertMsg = err!.localizedDescription
self.alert.toggle()
return
}
result?.user.sendEmailVerification(completion: { (err) in
if err != nil {
self.alertMsg = err!.localizedDescription
self.alert.toggle()
return
}
self.alertMsg = "Email verification has been sent. Verify your email."
self.alert.toggle()
})
}
}
func logOut() {
try! Auth.auth().signOut()
withAnimation {
self.status = false
}
email = ""
password = ""
email_SignUp = ""
password_SignUp = ""
reEnterPassword = ""
}
}
struct LoadingView : View {
@State var animation = false
var body: some View {
VStack {
Circle()
.trim(from: 0, to: 0.7)
.stroke(Color("Blue"), lineWidth: 8)
.frame(width: 75, height: 75)
.rotationEffect(.init(degrees: animation ? 360 : 0))
.padding(50)
}
.background(Color.white)
.frame(maxWidth: .infinity, maxHeight: .infinity)
.cornerRadius(20)
.background(Color.black.opacity(0.4).ignoresSafeArea(.all, edges: .all))
.onAppear(perform: {
withAnimation(Animation.linear(duration: 1)) {
animation.toggle()
}
})
}
}