I have a subclass of UITableView in my iOS app (Swift 4, XCode 9). This table has one row and I want it to display an alert when it's clicked, get some input from the user, and then update a label (lblUserFromPrefs
) in the table when the user clicks "OK" in the alert. Currently everything works fine except the label doesn't get updated. Here is the relevant code from my UITableView subclass:
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
print("Clicked section: \(indexPath.section) row: \(indexPath.row)")
let alert = UIAlertController(title: "Username", message: "what is your name", preferredStyle: .alert)
alert.addTextField { (textField) in
textField.text = ""
}
alert.addAction(UIAlertAction(title: "OK", style: .default, handler: { [weak alert] (_) in
let textField = alert!.textFields![0]
if let text = textField.text {
print("Text field: \(text)")
DispatchQueue.main.async {
self.lblUserFromPrefs.text = text
print("label updated")
}
}
}))
DispatchQueue.main.async {
self.present(alert, animated: true, completion: nil)
}
}
What happens when I run this is the label's text doesn't change when the alert closes but does change immediately when the table row is clicked again. I don't know why it waits until the row is clicked again to update the text. All the print statements print when I expect (including printing "label updated" immediately when the alert's OK button is pressed) and they print the right things. I know that when you're trying to update the UI from a closure in a background thread you have to use DispatchQueue.main.async {}
but I'm not sure why it's not updating even though I am using the main thread. I have tried using DispatchQueue.main.async(execute: {})
and putting self.lblUserFromPrefs.setNeedsDisplay()
directly after self.lblUserFromPrefs.text = "text"
. Any ideas what I'm doing wrong? Thanks!!
Add the
[weak self]
to the dispatch like this:Try something like this:
Here is the sample code for the behavior you want to achieve. Just include your alert controller code in didSelect and you should be good to go!