【问题标题】:Synchronous Authentication SwiftUI同步身份验证 SwiftUI
【发布时间】:2019-12-18 15:30:33
【问题描述】:

我正在使用需要登录的 SwiftUI 制作 iOS 应用程序。当按下创建帐户按钮时,该操作会触发我的 NetworkManager 类中的一个函数,该函数将输入的电子邮件和密码作为发布请求发送并接收适当的数据返回以进行身份​​验证。然后它使用接收到的数据来确定凭据是否有效

我的问题是它运行的代码会在实际收到响应之前根据 API 响应验证输入的凭据。因此,每次的结果都是相同的。

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)
}

我尝试过使用 DispatchQueue.main.async() 或创建自己的线程,但似乎没有任何效果。我需要找到一种方法来暂停主线程,以便在不使用 DispatchQueue.main.sync() 的情况下等待这行代码执行,因为这会导致死锁和程序崩溃。

这是向 API 发出 post 请求的函数的代码

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()
        }
    }
}

提前致谢!

【问题讨论】:

  • 不要试图强制异步任务变为同步。我确信networkManager 提供了一个带有完成处理程序的API。使用它。
  • @vadian 所以我应该只在它收到完成处理程序后运行 if 语句?
  • 是的,完成处理程序是一个异步调用的闭包。我不知道这个特定的NetworkManager 库。
  • 这就是我从 API 中提取的类。我会附上问题中的代码
  • 另外,您的按钮操作中不应包含类似的程序代码。 SwiftUI 是声明性的。关于登录成功或失败的逻辑应该在模型中。视图应该简单地绑定到模型中的适当属性。当登录成功或失败时,模型会更新,观察视图也会因绑定而更新。

标签: ios swift iphone xcode swiftui


【解决方案1】:

试试看:

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()
        }
    }
}

在你的函数中使用转义,我认为会得到准确的点服务器响应数据或得到错误。 我的英语太差了。

【讨论】:

  • 我会在按钮操作中的函数调用中添加什么以使其工作?
  • Xcode 会为你推荐原型函数,像这样: api.signUp(email: "abc", password: "aaa") { (error, response) in if error != nil { print( “错误=(错误)”)}否则{打印(“响应=(响应)”)}}
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-03-16
  • 2021-07-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多