0

I am very very new to swift development, and I'm trying to follow multiple different online tutorials to try and build a sign in page. Unfortunately all of the different views and models haven't slotted together well, and I'm having some issues.

The code below seems to work, apart from the ErrorView displaying. This code doesn't compile when the variables alert and error are @Published variable. It gives me the error ``Failed to produce diagnostics for expression". When I change them both to @State variables they don't update the view.

class AppViewModel: ObservableObject{
    @Published var signedIn = false
    @Published var alert = false;
    @Published var error = ""
    let auth = Auth.auth();

    func signIn(email: String, password: String){
        auth.signIn(withEmail: email, password: password) { [weak self] result, error in
            guard result != nil, error == nil else{
                self?.error = error!.localizedDescription
                print(error!.localizedDescription)
                self?.alert.toggle()
                return
            }
            
            DispatchQueue.main.async {
                self?.signedIn = true
            }
        }
    }
}

struct SignInView: View {
    @State var email = ""
    @State var password = ""
    @EnvironmentObject var viewModel: AppViewModel
       
    var body: some View {      
        VStack {
            if viewModel.alert {
                //SHOW ERROR        
                ErrorView(alert: viewModel.$alert, error: viewModel.$error)
                Text("errors")        
            }
            //SHOW SIGN IN FORM
            //THERE IS CODE HERE TO CALL THE AUTH FUNCTIONS VIA BUTTONS ETC BUT APPARENTLY I'M NOT ALLOWED TO PUT THE WHOLE FILE IN THIS QUESTION
        }
    }
}

If I used published variables I get an error Failed to produce diagnostic for expression; please file a bug report at var body: some View. If I use state variables then the ErrorView is never shown.

7
  • 2
    You need to edit your question to include all relevant code in the form of a minimal reproducible example in order to make the question on-topic. You have way too much code in your question, which makes it much harder for anyone else to pinpoint the issue. Commented May 17, 2021 at 14:01
  • @DávidPásztor I have done this now. Commented May 17, 2021 at 14:15
  • That error means that your code is broken in some way that the compiler can't identify. I would recommend commenting blocks of code until it compiles in order to figure out where is the offending block. Beyond that there isn't a lot we can figure out from that error message. Commented May 17, 2021 at 14:21
  • 1
    @ArianeHine Without ErrorView, we cannot solve the problem. Did you mean $viewModel.alert instead of viewModel.$alert? Commented May 17, 2021 at 14:21
  • You should also try to create appropriate Swift file for each important View Commented May 17, 2021 at 14:22

2 Answers 2

4

You should change viewModel.$alert to $viewModel.alert.

When you were using @State, the type of viewModel.$alert was Binding<Bool>. Now that you have changed it to @Published, like it should be, that type is now Published<Bool>.Publisher.

When you use $viewModel.alert, the type is Binding<Bool> correctly again.

Sign up to request clarification or add additional context in comments.

Comments

1

Change this

ErrorView(alert: viewModel.$alert, error: viewModel.$error)

to this

ErrorView(alert: $viewModel.alert, error: $viewModel.error)

Tips

Almost always, you should move any variables to your View Model. For example you have email and password as @State variables in your view. It makes much more sense to move those to your View Model. Why? You may later need to access them inside of a function or method in your VM itself. It's much easier to handle that if the data is already there. In your view you'd access it as Text(viewModel.email) or Text(viewModel.password). However if you need to validate that, inside your view model, it'll be readily accessible.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.