我遇到过这样的情况:我必须在注册和通过 OTP 代码登录时检查所提供的手机号码。我在我的 Accounts
类中进行了所有设置,以便在 SignUpViewController
和 SignInViewController
上重用它们。
在ViewControllers
中,我想先发送OTP,然后检查它是否是从服务器响应发送来推送VerificationViewController
,我正在使用Alamofire
用于网络,SwiftyJSON
用于解析 JSON 响应。现在让我们深入挖掘问题的核心:
这是我的 SignUpViewController
类的一部分
var acc: Accounts = Accounts()
@IBAction func signupAction(_ sender: Any) {
if validateFields() {
let fname = self.firstName.text!
let lname = self.lastName.text!
let pnum = self.phoneNumber.text!
self.acc.setFirstName(fn: fname)
self.acc.setLastName(ln: lname)
self.acc.setPhoneNumber(pn: pnum)
let result = self.acc.sendOTP()
if (result) {
let targetVC = UIStoryboard.init(name: "Main", bundle: Bundle.main).instantiateViewController(withIdentifier: "signupVerfication") as? SignupVerficationViewController
self.navigationController?.pushViewController(targetVC!, animated: true)
}
else {
CustomComponents().alertWithTitle(title: "Error", message: "Unable to Verify Phone Number,Please Try again!", ViewController: self)
}
}
}
这是我的 Accounts
类的一部分
func sendOTP() -> Bool {
let conf = APIConfig()
var returnedResult = false
conf.setURL(url: "patient/auth/send-totp")
conf.setHeader(head: ["Content-Type": "Application/json"])
conf.setBody(body: ["phone_number": self.phoneNumber])
print(self.phoneNumber)
Alamofire.request(conf.getURL(), method: .post, parameters: conf.getBody(), encoding: JSONEncoding.default, headers: conf.getHeader()).validate(statusCode: 200..<600).responseData { response in
let status = response.response?.statusCode
print(status!)
let swiftJSONVar = JSON(response.result.value!)
print(swiftJSONVar)
if (status == 200) {
returnedResult = true
}
}
return returnedResult
}
每当我运行应用程序时,我总是会收到警报作为输出,尽管事实上,如您所见,我通过在此处打印它 print(status!)
和此处 来调试响应打印(swiftJSONVar)
。打印的输出是 200
作为状态代码,我得到了其余的响应。
我一直在网上查找许多教程,例如:Grand Central Dispatch Tutorial for Swift 4和 Secure Coding With Concurrency in Swift 4等等,但无法在我的代码块上实现 GCD。
我需要你的帮助吗?
最佳答案
sendOTP 方法的返回类型为 Bool
,它会立即返回,因为 Alamofire
请求是异步
,并且您在顶部将 returnedResult 的值设置为 false,其中立即返回,无需等待响应。从 Alamofire 发出响应后,returnedResult 将设置为 true,但无法通知调用者。由于 sendOTP 方法返回 false,因此显示错误警报。
使用闭包而不是从 sendOTP 返回 bool,后者接受 Bool 并返回 void
func sendOTP(_ completion: @escaping (Bool) -> Void) {
let conf = APIConfig()
var returnedResult = false
conf.setURL(url: "patient/auth/send-totp")
conf.setHeader(head: ["Content-Type": "Application/json"])
conf.setBody(body: ["phone_number": self.phoneNumber])
print(self.phoneNumber)
Alamofire.request(conf.getURL(), method: .post, parameters: conf.getBody(), encoding: JSONEncoding.default, headers: conf.getHeader()).validate(statusCode: 200..<600).responseData { response in
let status = response.response?.statusCode
print(status!)
let swiftJSONVar = JSON(response.result.value!)
print(swiftJSONVar)
if (status == 200) {
completion(true)
} else {
completion(false)
}
}
}
现在你可以打电话了
self.acc.sendOTP { (result) in
if result {
//show vc
let targetVC = UIStoryboard.init(name: "Main", bundle: Bundle.main).instantiateViewController(withIdentifier: "signupVerfication") as? SignupVerficationViewController
self.navigationController?.pushViewController(targetVC!, animated: true)
} else {
//show error alert
CustomComponents().alertWithTitle(title: "Error", message: "Unable to Verify Phone Number,Please Try again!", ViewController: self)
}
}
连同 GCD教程,我推荐URLSession和 Alamofire教程以及了解网络在 iOS 中如何工作。
关于ios - 在 swift 4 中返回之前强制等待 Alamofire 响应,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53516425/