Home > Software engineering >  Why ViewModel function is throwing error in SwiftUI?
Why ViewModel function is throwing error in SwiftUI?

Time:11-06

I am trying to call ViewModel method in the view but getting error as Thread 1: Fatal error: No ObservableObject of type AuthViewModel found. A View.environmentObject(_:) for AuthViewModel may be missing as an ancestor of this view. I don't have any idea why it is happening.

AuthViewModel

import SwiftUI

class AuthViewModel: ObservableObject {
  func login() {
    print("Hello")
  }
}

My View File

//
//  RegistrationView.swift
//  TwitterSwiftUI
//
//  Created by developer on 11/06/21.
//

import SwiftUI

struct RegistrationView: View {
  @State var text = ""
  @State var fullName = ""
  @State var userName = ""
  @State var password = ""
  @State var isImagePickerDisplay = false
  @State var selectedImage:UIImage?
  
  @Environment(\.presentationMode) var mode: Binding<PresentationMode>
  
  @EnvironmentObject var viewModel: AuthViewModel
    var body: some View {

      ZStack {
        Color(#colorLiteral(red: 0.2203325033, green: 0.6315936446, blue: 0.955042541, alpha: 1))
          .ignoresSafeArea()
        VStack {
          
          Button(action: {
            isImagePickerDisplay = true
          }, label: {
            
            if selectedImage != nil {
                Image(uiImage: selectedImage!)
                .resizable()
                .scaledToFit()
                .frame(width: 140, height: 140)
                .padding(.top, 0)
            } else {
              Image("plus_photo")
                .resizable()
                .renderingMode(/*@START_MENU_TOKEN@*/.template/*@END_MENU_TOKEN@*/)
                .foregroundColor(.white)
                .scaledToFit()
                .frame(width: 140, height: 140)
                .padding(.top, 0)
            }

            
            
          })
          
          
          
          VStack {
            CustomTextField(text: $fullName, placeholder: Text("Full name"), icon: Image(systemName: "person"))
              .foregroundColor(.white)
              .padding()
              .background(Color(.init(white: 1, alpha: 0.15)))
              .cornerRadius(10)
            
            CustomTextField(text: $fullName, placeholder: Text("Email"), icon: Image(systemName: "envelope"))
              .foregroundColor(.white)
              .padding()
              .background(Color(.init(white: 1, alpha: 0.15)))
              .cornerRadius(10)
            
            CustomTextField(text: $userName, placeholder: Text("Username"), icon: Image(systemName: "person"))
              .foregroundColor(.white)
              .padding()
              .background(Color(.init(white: 1, alpha: 0.15)))
              .cornerRadius(10)
            
            CustomSecureField(password: $password)
              .foregroundColor(.white)
              .padding()
              .background(Color(.init(white: 1, alpha: 0.15)))
              .cornerRadius(10)
            Spacer()
              .frame(height: 30)
            
            GeometryReader { geometry in
              Button(action: {
                //viewModel.registerUser(email: "userName", password: "password", userName: "userName", fullName: "fullName", profileImage: selectedImage)
                viewModel.login()
              }, label: {
                  Text("Sign up")
              })
              .frame(width: (geometry.size.width*1), height: 50)
              .background(Color.white)
              .clipShape(Capsule())
              .padding(.vertical)
            }
            
          }.padding()
            
          Spacer()
          
          HStack {
            Text("Already have account? Login in")
              .foregroundColor(.white)
          }.onTapGesture {
            mode.wrappedValue.dismiss()
          }.padding(.bottom, 28)
          
          
          
          
        }
      }.sheet(isPresented: self.$isImagePickerDisplay) {
        ImagePickerViewHelper(selectedImage: self.$selectedImage, sourceType: .photoLibrary)
      }
      
    }
}

CodePudding user response:

The error message clearly says that the @EnvironmentObject property wrapper requires the associated object to be added to the environment somewhere on a higher level of the view hierarchy with the environmentObject() modifier.

To access the view model directly you have to use @Stateobject to create an instance of the observed class

@Stateobject var viewModel = AuthViewModel()
  • Related