UI 虽然使用主线程但未获得更新
UI is not getting update although using main thread
我正在使用 Xcode 和 Swift。我有一个 class 用于我正在使用的 UIViewController
。在这个 UIViewController
上,我想用我的自定义 class ConnectionLostView
呈现某种弹出式视图。在这个 UIView
上有一个 UIButton
。如果您按下按钮,将调用 tryToReconnect()
函数(有效)。此功能处理在线数据(也有效)并且应该使用 DispatchQueue.main.async { //updating UI }
更新我的 UI 但我的 UI 没有更新(或者更确切地说我不能即从中删除我的按钮它的 superview 但我可以删除 self (什么有效,什么无效,你可以在下面的代码中看到注释))
那是 class 的 UIViewController
我用来表达我的观点。
class vc: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let connectionStatusView = ConnectionLostView()
connectionStatusView.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(connectionStatusView)
//setting up the constraints for connectionStatusView
}
}
这是我的 UIView
的 class:
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
}
}
如何修复我的代码,以便在我按下 reconnectButton
时更新 UI?
实际上,线程和调度队列是转移注意力的问题。问题仅仅是 self.tryAgainButton
是对不在界面中的按钮的引用。它在某处思考-space。它没有超级视图并且不可见。因此你调用 removeFromSuperview
并没有任何反应。
您确实在界面中添加了一个按钮 (reconnectButton
)。 [你这样做的方式完全错误,但你这样做的方式有什么问题将是另一个问题的主题!] 但是你从未将 self.tryAgainButton
设置为 reconnectButton
,所以它们不是相同的按钮。你有 两个 按钮,一个在界面中 (reconnectButton
) 一个在思想中 - space (self.tryAgainButton
).
你的class看起来像
class ConnectionLostView: UIView {
let reconnectButton = UIButton(type: .roundedRect)
@objc func tryToReconnect() {
}
override init(frame: CGRect) {
super.init(frame: frame)
let buttonAttributes = [NSAttributedString.Key.foregroundColor: UIColor.white, NSAttributedString.Key.font: UIFont.boldSystemFont(ofSize: 18)]
let attributedButtonString = NSAttributedString(string: "Try To Reconnect", attributes: buttonAttributes)
reconnectButton.translatesAutoresizingMaskIntoConstraints = false
reconnectButton.setAttributedTitle(attributedButtonString, for: .normal)
reconnectButton.addTarget(self, action: #selector(tryToReconnect), for: .touchUpInside)
addSubview(reconnectButton)
// add constraints for the button
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
我正在使用 Xcode 和 Swift。我有一个 class 用于我正在使用的 UIViewController
。在这个 UIViewController
上,我想用我的自定义 class ConnectionLostView
呈现某种弹出式视图。在这个 UIView
上有一个 UIButton
。如果您按下按钮,将调用 tryToReconnect()
函数(有效)。此功能处理在线数据(也有效)并且应该使用 DispatchQueue.main.async { //updating UI }
更新我的 UI 但我的 UI 没有更新(或者更确切地说我不能即从中删除我的按钮它的 superview 但我可以删除 self (什么有效,什么无效,你可以在下面的代码中看到注释))
那是 class 的 UIViewController
我用来表达我的观点。
class vc: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let connectionStatusView = ConnectionLostView()
connectionStatusView.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(connectionStatusView)
//setting up the constraints for connectionStatusView
}
}
这是我的 UIView
的 class:
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
}
}
如何修复我的代码,以便在我按下 reconnectButton
时更新 UI?
实际上,线程和调度队列是转移注意力的问题。问题仅仅是 self.tryAgainButton
是对不在界面中的按钮的引用。它在某处思考-space。它没有超级视图并且不可见。因此你调用 removeFromSuperview
并没有任何反应。
您确实在界面中添加了一个按钮 (reconnectButton
)。 [你这样做的方式完全错误,但你这样做的方式有什么问题将是另一个问题的主题!] 但是你从未将 self.tryAgainButton
设置为 reconnectButton
,所以它们不是相同的按钮。你有 两个 按钮,一个在界面中 (reconnectButton
) 一个在思想中 - space (self.tryAgainButton
).
你的class看起来像
class ConnectionLostView: UIView {
let reconnectButton = UIButton(type: .roundedRect)
@objc func tryToReconnect() {
}
override init(frame: CGRect) {
super.init(frame: frame)
let buttonAttributes = [NSAttributedString.Key.foregroundColor: UIColor.white, NSAttributedString.Key.font: UIFont.boldSystemFont(ofSize: 18)]
let attributedButtonString = NSAttributedString(string: "Try To Reconnect", attributes: buttonAttributes)
reconnectButton.translatesAutoresizingMaskIntoConstraints = false
reconnectButton.setAttributedTitle(attributedButtonString, for: .normal)
reconnectButton.addTarget(self, action: #selector(tryToReconnect), for: .touchUpInside)
addSubview(reconnectButton)
// add constraints for the button
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}