Swift 在解释响应之前,如何确保此函数已完成?
我对Swift有些陌生,在这个网站的帮助下,我基本上已经学会了如何使用完成处理程序。经过几天的努力,我希望能得到更多的直接帮助 我有一个:Swift 在解释响应之前,如何确保此函数已完成?,swift,asynchronous,completionhandler,Swift,Asynchronous,Completionhandler,我对Swift有些陌生,在这个网站的帮助下,我基本上已经学会了如何使用完成处理程序。经过几天的努力,我希望能得到更多的直接帮助 我有一个: @IBAction func submitRegistrationButton(_ sender: Any) { if((firstNameField.text?.trimmingCharacters(in: .whitespacesAndNewlines).characters.count) == 0){ showXAlert(t
@IBAction func submitRegistrationButton(_ sender: Any) {
if((firstNameField.text?.trimmingCharacters(in: .whitespacesAndNewlines).characters.count) == 0){
showXAlert(title: "Oops!", message: "Please enter your first name.", viewController: self)
}else if((lastNameField.text?.trimmingCharacters(in: .whitespacesAndNewlines).characters.count) == 0){
showXAlert(title: "Oops!", message: "Please enter your last name.", viewController: self)
}else if((emailAddressField.text?.trimmingCharacters(in: .whitespacesAndNewlines).characters.count) == 0){
showXAlert(title: "Oops!", message: "Please enter your email address.", viewController: self)
}else if !isValidEmail(testStr: emailAddressField.text!){
showXAlert(title: "Oops!", message: "Please enter a valid email address.", viewController: self)
}else if((passwordField.text?.trimmingCharacters(in: .whitespacesAndNewlines).characters.count) == 0){
showXAlert(title: "Oops!", message: "Please enter a password.", viewController: self)
}else if passwordField.text != passwordConfirmationField.text{
showXAlert(title: "Oops!", message: "Your password and password confirmation do not match. Please correct.", viewController: self)
}else{
registrant.firstName = firstNameField.text!
registrant.lastName = lastNameField.text!
registrant.zipCode = zipCodeField.text!
registrant.emailAddress = emailAddressField.text!
registrant.password = passwordField.text!
storeRegistrationInfo(registrant: registrant) { (object: XUserAPIResult) in
print("submissionStatus = \(object.success)")
if object.success == 1 {
showXAlert(title: "Welcome \(self.registrant.firstName)!", message: "Your registration was submitted successfully. Log in by clicking the Login button below", viewController: self)
}else{
showXAlert(title: "Un Oh", message: "There was a problem with your registration. \(object.errorMessage)", viewController: self)
}
}
}
}
…这就要求:
func storeRegistrationInfo(registrant: XRegistrantInfo, finished: @escaping (XUserAPIResult)->()) {
var apiResult = XUserAPIResult()
let appDelegate = UIApplication.shared.delegate as! AppDelegate
let context = appDelegate.persistentContainer.viewContext
let newRegistrant = NSEntityDescription.insertNewObject(forEntityName: "User", into: context)
let requestURL = NSURL(string: USER_API_URL)
let request = NSMutableURLRequest(url: requestURL! as URL)
request.httpMethod = "POST"
newRegistrant.setValue(registrant.firstName, forKey: "firstName")
newRegistrant.setValue(registrant.lastName, forKey: "lastName")
newRegistrant.setValue(registrant.zipCode, forKey: "zipCode")
newRegistrant.setValue(registrant.emailAddress, forKey: "emailAddress")
newRegistrant.setValue(registrant.password, forKey: "password")
newRegistrant.setValue(registrant.personna, forKey: "personna")
do{
try context.save()
let postParameters = "tag=" + REGISTRATION_API_TAG + "&firstName=" + registrant.firstName + "&lastName=" + registrant.lastName + "&password=" + registrant.password + "&username=" + registrant.emailAddress + "&personna=" + registrant.personna + "&zipCode=" + registrant.zipCode
request.httpBody = postParameters.data(using: .utf8)
let task = URLSession.shared.dataTask(with: request as URLRequest){
data, response, error in
if error != nil{
print("error is \(error)")
return
}
print("response = \(response)")
//parsing the response
do {
//converting resonse to NSDictionary
let myJSON = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as? NSDictionary
//parse json 2
if let dictionary = myJSON as? [String: Any]{
if let apiSuccess = dictionary["success"] as? Int{
apiResult.success = apiSuccess
}
if let apiError = dictionary["error"] as? Int{
apiResult.error = apiError
if apiError != 0{
if let apiErrorMessage = dictionary["error_msg"] as? String{
apiResult.errorMessage = apiErrorMessage
}
}else{
if let apiUID = dictionary["uid"] as? String{
apiResult.uniqueID = apiUID
}
if let nestedDictionary = dictionary["user"] as? [String: Any]{
if let apiFirstName = nestedDictionary["firstName"] as? String{
apiResult.user.firstName = apiFirstName
}
if let apiLastName = nestedDictionary["lastName"] as? String{
apiResult.user.lastName = apiLastName
}
if let apiEmail = nestedDictionary["e-mail"] as? String{
apiResult.user.emailAddress = apiEmail
}
if let apiCreatedAt = nestedDictionary["created_at"] as? String{
apiResult.user.createdAt = apiCreatedAt
}
if let apiPersonna = nestedDictionary["personna"] as? String{
apiResult.user.personna = apiPersonna
}
}
finished(apiResult)
}
}
}
} catch {
print(error)
}
}
task.resume()
finished(apiResult)
} catch {
print("There was an error saving to Core Data")
finished(apiResult)
}
}
submitRegistrationButton()代码应该等待storeRegistrationInfo()返回一个XUserAppResult结构,然后根据XUserAppResult的成功属性显示相应的警报
问题是成功检查代码在storeRegistrationInfo()完成JSON解析之前执行;显示错误的警报,然后在解析JSON后正确执行。代码的其他方面(web API调用、解析JSON、将数据保存到web数据库)也可以工作
我很确定我使用完成处理程序或调用storeRegistrationInfo()的方式有问题,但我不确定确切的修复方法
如何确保@IBAction func submitRegistrationButton(u-sender:Any)中的警报代码:
storeRegistrationInfo(registrant: registrant) { (object: XUserAPIResult) in
print("submissionStatus = \(object.success)")
if object.success == 1 {
showXAlert(title: "Welcome \(self.registrant.firstName)!", message: "Your registration was submitted successfully. Log in by clicking the Login button below", viewController: self)
}else{
showXAlert(title: "Un Oh", message: "There was a problem with your registration. \(object.errorMessage)", viewController: self)
}
}
…仅在解析JSON并填充并传回UserAPIResult结构后调用
谢谢。试试下面的方法
typealias CompletionHandler = (data:XRegistrantInfo,success:Bool) -> Void;
func storeRegistrationInfo(registrant: XRegistrantInfo,completionHandler: CompletionHandler) {
// your code.
//
//
completionHandler(data: dataToReturn,success : true/false)
}
电话号码如下:
storeRegistrationInfo(registrant, { (data,success) -> Void in
//onCompletion the code will go here
if success {
// success
} else {
// fail
}
})
代码中的问题是这里的一行:
task.resume()
finished(apiResult)
您应该删除对finished
完成处理程序的调用,因为在获得响应后,应该在已放置的位置调用该处理程序
另一个改进建议是简化字段验证代码,以使用
guard
语句。谢谢!看来已经修好了!我会按照你关于守卫声明的建议……我在上面说“似乎”,因为在显示“欢迎…”警报后,应用程序现在正在崩溃。但是我不知道这是否有关系。为了结束这个问题以及其他遇到同样问题的人,感谢我意识到showXAlert()
试图从主线程以外的线程发出警报。这就是造成坠机的原因谢谢Moin。我刚刚对typealias
做了一些快速的研究。您建议这样做是为了提高代码的可维护性/可读性吗?你为什么要检查xUserAppResult实例的success:Bool
属性,而不是我现在看到的success:Int
属性?如果返回类型只是在两个值之间切换,那么我通常更喜欢使用Bool,如果它的顺序大于但在一个序列中,那么使用enum