I am using Xcode and Swift. I have a class for the UIViewController
I am using. On this UIViewController
I want to present some kind of pop over view with my custom class ConnectionLostView
. On this UIView
there is an UIButton
. If you press the button the tryToReconnect()
function is called (which works). This function processes the online data (which works too) and should update my UI using DispatchQueue.main.async { //updating UI }
but my UI isn't getting updated (or rather I can't i.e. remove my button from its superview but I can remove self (what exactly works and what doesn't you can see as comment in the code below))
That is the class of the UIViewController
I am using to present my view.
class vc: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let connectionStatusView = ConnectionLostView()
connectionStatusView.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(connectionStatusView)
//setting up the constraints for connectionStatusView
}
}
This is the class of my UIView
:
class ConnectionLostView: UIView {
let tryAgainButton = UIButton(type: .roundedRect)
func tryToReconnect() {
let url = URL(string: "http://worldclockapi.com/api/json/est/now")!
let config = URLSessionConfiguration.default
let session = URLSession(configuration: config)
let task = session.dataTask(with: url) { (data, response, error) in
if error != nil {
print(error)
} else {
do {
if let json = try JSONSerialization.jsonObject(with: data!, options: .allowFragments) as? [String: Any] {
if let data = json["data"] as? String {
// code for processing the data
DispatchQueue.main.async {
self.removeFromSuperview() //Does work
self.tryAgainButton.removeFromSuperview() // does not work
}
}
}
} catch {
print(error)
}
}
}
}
override func draw(_ rect: CGRect) {
super.draw(rect)
//setting up the button
let buttonAttributes = [NSAttributedString.Key.foregroundColor: UIColor.white, NSAttributedString.Key.font: UIFont.boldSystemFont(ofSize: 18)]
let attributedButtonString = NSAttributedString(string: "Try To Reconnect", attributes: buttonAttributes)
let reconnectButton = UIButton(type: .roundedRect)
reconnectButton.translatesAutoresizingMaskIntoConstraints = false
reconnectButton.setAttributedTitle(attributedButtonString, for: .normal)
reconnectButton.addTarget(self, action: #selector(tryToReconnect), for: .touchUpInside)
addSubview(reconnectButton)
// setting up constraints for reconnectButton
}
}
How can I fix my code so the UI is updated when I press the reconnectButton
?
Actually, the thread and the dispatch queue are red herrings. The problem is merely that self.tryAgainButton
is a reference to a button that is not in the interface to begin with. It is off in thought-space somewhere. It has no superview and is not visible. Therefore you call removeFromSuperview
on it and nothing happens.
You did add a button to the interface (reconnectButton
). [You did that in a completely wrong way, but what's wrong with the way you did it would be a subject for a different question!] But you never set self.tryAgainButton
to reconnectButton
, so they are not the same buttons. You have two buttons, the one in the interface (reconnectButton
) and the one off in thought-space (self.tryAgainButton
).