Search code examples
iosswiftalertuialertcontroller

In Swift, Commands in alert closure executed before UI alert be executed?


Based on the following code, commands in closure in alert function are executed before User interface be executed. It causes, the variables in closure be empty?

func callAlert2() {
    let alert = UIAlertController(title: "Add Contact", message: "Please fill the form", preferredStyle: .alert)


    alert.addTextField { textField in
        textField.placeholder = "Name"
        self.contact.name = textField.text
    }

    alert.addTextField { (textField) in
        textField.placeholder = "Surname"
        self.contact.surname = textField.text
    }

    alert.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: nil))
    alert.addAction(UIAlertAction(title: "Add", style: .default, handler: { (action) in
        if let name = alert.textFields?.first?.text {        
            self.allContacts.append(self.contact)
        }
    }))


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

Solution

  • Seems like you miss understood addTextField(configurationHandler:) as per docs

    A block for configuring the text field prior to displaying the alert. This block has no return value and takes a single parameter corresponding to the text field object. Use that parameter to change the text field properties.

    Link: https://developer.apple.com/documentation/uikit/uialertcontroller/1620093-addtextfield

    You are expecting your self.contact object's name and surname to be updated inside configuration block but that will never happen. This closure/block is intended only for configuring the textfield and not to capture user input.

    Inside this closure you can modify textFields property like placeholder, background color, border etc etc to configure it before being rendered. But if you want to capture the user input, use actions closure.

    Rather

    alert.addAction(UIAlertAction(title: "Add", style: .default, handler: { (action) in
                if let name = alert.textFields?.first?.text,
                    (alert.textFields?.count ?? 0) >= 1,
                    let surname = alert.textFields?[1].text {
                    self.contact.name = name
                    self.contact.surname = surname
                    self.allContacts.append(self.contact)
                }
            }))
    

    Hope this helps