简体   繁体   中英

Synchronous Authentication SwiftUI

I am making an iOS app using SwiftUI that requires login. When the create account button is pressed, the action triggers a function in my NetworkManager class that sends the inputed email and password as a post request and receives the appropriate data back for authentication. It then uses the received data to determine whether the credentials are valid

My issue is that it runs the code that verifies the inputed credentials against the API response before the response is actually received. Consequently, the result is the same each time.

Button(action: {


    self.networkManager.signUp(email: self.inputEmail, password: self.inputPassword)

    // These if statements run before the above line is executed
    if self.networkManager.signUpResponse.code == nil {
        // SUCCESSFUL REGISTRATION
        ProgressHUD.showSuccess("Account Successfully Created!")
        UserDefaults.standard.set(true, forKey: "LoggedIn")
        self.showingWelcomePage = false
    }

    if self.networkManager.signUpResponse.code == 201 {
        // REGISTRATION FAILED
        ProgressHUD.showError("This account already exists", interaction: false)
    }

}) {

    Text("Create Account")
        .font(.headline)
}

I have tried using DispatchQueue.main.async() or creating my own thread, however nothing seems to work. I need to find a way to pause the main thread in order to wait for this line of code to execute before proceeding without using DispatchQueue.main.sync() as this results in deadlock and program crash.

Here is the code for the function that makes the post request to the API

class NetworkManager: ObservableObject {

    @Published var signUpResponse = AccountResults()

    func signUp(email: String, password: String) {

        if let url = URL(string: SignUpAPI) {
            let session = URLSession.shared

            let bodyData = ["school": "1",
                            "email": email,
                            "password": password]

            var request = URLRequest(url: url)
            request.httpMethod = "POST"
            request.httpBody = try! JSONSerialization.data(withJSONObject: bodyData)

            let task = session.dataTask(with: request) { (data, response, error) in
                if error == nil {
                    let decoder = JSONDecoder()
                    if let safeData = data {
                        do {
                            let results = try decoder.decode(AccountResults.self, from: safeData)

                            DispatchQueue.main.async {

                                self.signUpResponse = results

                            }
                        } catch {
                            print(error)
                        }
                    }
                }

            }
            task.resume()
        }
    }
}

Thanks in advance!

Try it:

 func signUp(email: String, password: String, completion: @escaping((Error?, YourResponse?) -> Void)) { if let url = URL(string: SignUpAPI) { let session = URLSession.shared let bodyData = ["school": "1", "email": email, "password": password] var request = URLRequest(url: url) request.httpMethod = "POST" request.httpBody = try! JSONSerialization.data(withJSONObject: bodyData) let task = session.dataTask(with: request) { (data, response, error) in if error == nil { let decoder = JSONDecoder() if let safeData = data { do { let results = try decoder.decode(AccountResults.self, from: safeData) DispatchQueue.main.async { self.signUpResponse = results completion(nil, results) } } catch { print(error) completion(error, nil) } } } } task.resume() } } }

use escaping in your function, I think will get exactly the point server response data or get errors too. my english is so bad.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM