【问题标题】:UI is not getting update although using main thread尽管使用主线程,但 UI 没有得到更新
【发布时间】:2019-03-03 16:08:35
【问题描述】:

我正在使用 Xcode 和 Swift。我有一个我正在使用的UIViewController 的课程。在这个UIViewController 上,我想用我的自定义类ConnectionLostView 呈现某种弹出视图。在这个UIView 上有一个UIButton。如果您按下按钮,则会调用 tryToReconnect() 函数(有效)。此函数处理在线数据(也可以)并且应该使用DispatchQueue.main.async { //updating UI } 更新我的 UI,但我的 UI 没有得到更新(或者我不能即从其超级视图中删除我的按钮,但我可以删除 self(究竟是什么有效,你不能在下面的代码中看到什么作为注释))

这是我用来展示我的观点的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 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?

【问题讨论】:

  • 你确定吗,你的 DispatchQueue.main.async 块被调用了。 URL(worldclockapi.com/api/json/est/now) 的响应没有返回任何字段“数据”。 "if let data = json["data"]" 可能为零。
  • 问题已经解决了,但是它被调用了

标签: ios swift user-interface urlsession networkonmainthread


【解决方案1】:

实际上,线程和调度队列是红鲱鱼。问题仅仅是self.tryAgainButton 是对不在界面中的按钮的引用。它在思想空间的某个地方关闭。它没有超级视图并且不可见。因此,您调用 removeFromSuperview 并没有任何反应。

您确实在界面中添加了一个按钮 (reconnectButton)。 [您以完全错误的方式这样做,但是您这样做的方式有什么问题将成为另一个问题的主题!] 但是您从未将 self.tryAgainButton 设置为 reconnectButton,因此它们不是相同的按钮。您有两个按钮,一个在界面中(reconnectButton),一个在思想空间中(self.tryAgainButton)。

【讨论】:

  • 但是现在你需要修复你的代码。 draw 绝对不是向视图添加按钮的地方。它会被调用很多次,所以你最终会得到数千个按钮。在draw 中你唯一应该做的就是画图。
  • 你建议我在哪里添加按钮
  • Sh_Khan 给了你一个建议。但这是一个在 Stack Overflow 上已经处理过很多次的话题,所以我没有必要参与其中。
【解决方案2】:

你的班级看起来像

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")
    }

}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多