尽管使用主线程,UI仍未更新

时间:2019-03-03 16:08:36

标签: ios swift user-interface urlsession networkonmainthread

我正在使用Xcode和Swift。我正在使用UIViewController的类。在此UIViewController上,我想用自定义类ConnectionLostView展示某种弹出式视图。在此UIView上有一个UIButton。如果按下按钮,将调用tryToReconnect()函数(有效)。此函数处理在线数据(也可以使用),并且应该使用DispatchQueue.main.async { //updating UI }更新我的UI,但是我的UI尚未更新(或者我不能从其超级视图中删除按钮,但是我可以删除自身(到底什么有效,在下面的代码中您看不到什么))

这是我用来表达自己观点的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?

2 个答案:

答案 0 :(得分:2)

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

您确实在界面(reconnectButton)中添加了一个按钮。 [您以完全错误的方式进行了此操作,但是您的操作方式出了什么问题将是另一个问题的主题!]但是您从未将self.tryAgainButton设置为reconnectButton,因此它们并不是相同的按钮。您有两个 按钮,一个位于界面(reconnectButton)中,一个处于思考空间(self.tryAgainButton)中。

答案 1 :(得分:1)

您的课程看起来像

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

}