简体   繁体   中英

Implementing Completion Block swift

I have implemented completion block which has a logic error. I want when the checkOutBtn is clicked checkFields is triggered first to check if all the text fields is not empty before it triggers the addingDeliveryAddress() method to insert into the database before performing the sesueway. But its not working like that when checkOutBtn is clicked it goes ahead and perform the segueway. Thanks all for your help. Thanks

   @IBAction func checkOutBtn(_ sender: Any) {

    checkFields { (results) in
        if results {
            self.addingDeliveryAddress()
        }
    }
}


func checkFields(_ completion: @escaping (Bool) -> ()){
        if (recipientName.text?.isEmpty)! {
            errorMessageLbl.textColor = UIColor.red
            errorMessageLbl.text = "Enter Recipient Name"
            completion(false)
        }else if (recipientMobile.text?.isEmpty)! {
            errorMessageLbl.textColor = UIColor.red
            errorMessageLbl.text = "Enter Recipient Mobile Number"
            completion(false)
        }else if (recipientArea.text?.isEmpty)! {
            errorMessageLbl.textColor = UIColor.red
            errorMessageLbl.text = "Enter Recipient Area"
            completion(false)
        }else if (recipientAddress.text?.isEmpty)! {
            errorMessageLbl.textColor = UIColor.red
            errorMessageLbl.text = "Enter Recipient Address"
            completion(false)
        }
        completion(true)
    }



    //Adding Delivery Address
    func addingDeliveryAddress(){

        //getting user data from defaults
        let defaultValues = UserDefaults.standard
        let userId = defaultValues.string(forKey: "userid")

        //creating parameters for the post request
        let parameters: Parameters=[
            "recipientName":recipientName.text!,
            "recipientPhoneNumber":recipientMobile.text!,
            "recipientArea":recipientArea.text!,
            "recipientAddress":recipientAddress.text!,
            "nearestLandmark":recipientLandmark.text!,
            "userId":Int(userId!)!
        ]

        //Constant that holds the URL for web service
        let URL_ADD_DELIVERY_ADDRESS = "http://localhost:8888/restaurant/addDeliveryAddress.php?"

        Alamofire.request(URL_ADD_DELIVERY_ADDRESS, method: .post, parameters: parameters).responseJSON {
            response in
            //printing response
            print(response)

            let result = response.result.value

            //converting it as NSDictionary
            let jsonData = result as! NSDictionary

            //if there is no error
            if(!(jsonData.value(forKey: "error") as! Bool)){

                self.performSegue(withIdentifier: "toCheckOut", sender: self)

            }else{

                let alert = UIAlertController(title: "No Delivery Address", message: "Enter Delivery Address to continue", preferredStyle: .alert)

                alert.addAction(UIAlertAction(title: "Ok", style: .destructive, handler: nil))
                //alert.addAction(UIAlertAction(title: "No", style: .cancel, handler: nil))

                self.present(alert, animated: true)
            }
        }
    }

Why a completion block? There is no asynchronous process.

I suggest this way which returns (directly) the error string or an empty string on success.

@IBAction func checkOutBtn(_ sender: Any) {

    let result = checkFields()
    if result.isEmpty {
        self.addingDeliveryAddress()
    } else {
       errorMessageLbl.textColor = UIColor.red
       errorMessageLbl.text = "Enter Recipient " + result
    }
}

func checkFields() -> String {
    if recipientName.text!.isEmpty {
        return "Name"
    } else if recipientMobile.text!.isEmpty {
        return "Mobile Number"
    } else if recipientArea.text!.isEmpty {
        return "Area"
    } else if recipientAddress.text!.isEmpty {
        return "Address"
    }
    return ""
}

In your code you're using @escaping in closure. It's wrong as you're not doing anything asynchronous in this closure body. When using @escaping the closure is being preserve to be execute later and function's body gets executed. That's why addingDeliveryAddress() gets triggered before checking anything. Your closure function should be @nonescaping like this..

func checkFields(_ completion: (Bool) -> ()){
        if (recipientName.text?.isEmpty)! {
            errorMessageLbl.textColor = UIColor.red
            errorMessageLbl.text = "Enter Recipient Name"
            completion(false)
        }else if (recipientMobile.text?.isEmpty)! {
            errorMessageLbl.textColor = UIColor.red
            errorMessageLbl.text = "Enter Recipient Mobile Number"
            completion(false)
        }else if (recipientArea.text?.isEmpty)! {
            errorMessageLbl.textColor = UIColor.red
            errorMessageLbl.text = "Enter Recipient Area"
            completion(false)
        }else if (recipientAddress.text?.isEmpty)! {
            errorMessageLbl.textColor = UIColor.red
            errorMessageLbl.text = "Enter Recipient Address"
            completion(false)
        }
        completion(true)
    }

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