在我解释响应之前如何确保此函数完成?

How Can I Make Sure This Function Completes Before I Interpret The Response?

我是 Swift 的新手,并且在本网站的帮助下基本上已经了解了如何使用完成处理程序。经过几天的尝试使其正常工作,我将不胜感激更直接的帮助。

我有一个:

@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() returns a XUser APIResult struct 然后根据 XUserAPIResult 的成功显示适当的警报 属性.

问题是在 storeRegistrationInfo() 完成解析 JSON 之前执行成功检查代码;显示错误警报,然后在解析 JSON 后正确执行。代码的其他方面(网络 API 调用、解析 JSON、将数据保存到网络数据库)有效。

我很确定我使用完成处理程序或调用 storeRegistrationInfo() 的方式有问题,但我不确定如何修复它。

如何确保 @IBAction func submitRegistrationButton(_ 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 语句。