首页 > 解决方案 > 用于更新视图的 Swift 主循环

问题描述

我是 Swift 的新手,正在尝试实现一个简单的测试单视图应用程序:运行时,它应该UITextView自动在 a 中添加文本行。

但是,我得到的只是一个带有以下代码的空白屏幕:

import UIKit

class ViewController: UIViewController {
    @IBOutlet weak var m_logView: UITextView!

    private let m_log = Log()
    override func viewDidLoad() {
        super.viewDidLoad()
        addLog(msg: "Hello World!")

        while true {
            m_log.requestLog{ [weak self] (data: String) in
                self?.consumeLog(log: data)
            }
        }
    }

    func consumeLog(log: String) {
        addLog(msg: log)
    }

    func addLog(msg: String) {
        m_logView.text += msg + "\n"
    }
}

class Log {
    func requestLog(consume: (_ log: String) -> Void) {
        let log = "Data from wherever"
        consume(log)
    }
}

我怀疑我试图UITextView在错误的地方更新。上面的代码只是阻止了viewDidLoad()完成自身并显示UITextView.

所以我找到了viewDidAppear,但这次它卡在那里并且只显示“Hello World!” 在视图中。

import UIKit

class ViewController: UIViewController {
    @IBOutlet weak var m_logView: UITextView!

    private let m_log = Log()
    override func viewDidLoad() {
        super.viewDidLoad()
        addLog(msg: "Hello World!")
    }

    override func viewDidAppear(_ animated: Bool) {
        while true {
            m_log.requestLog{ [weak self] (data: String) in
                self?.consumeLog(log: data)
            }
        }
    }

    func consumeLog(log: String) {
        addLog(msg: log)
    }

    func addLog(msg: String) {
        m_logView.text += msg + "\n"
    }
}

class Log {
    func requestLog(consume: (_ log: String) -> Void) {
        let log = "Data from wherever"
        consume(log)
    }
}

我发现的大多数 iOS MVC 教程都教如何实现用户交互,但远离如何通过以编程方式从后端更改模型来更新视图。

我可能正在寻找一个回调/委托,UITextView只要数据发生变化,我就可以在其中刷新与其数据模型相关的链接,但它在哪里?

标签: iosswiftmodel-view-controller

解决方案


while循环是完全不合适的,因为它会导致死锁。

使用Timer异步工作的 a

代替

while true {
    m_log.requestLog{ [weak self] (data: String) in
        self?.consumeLog(log: data)
    }
}

Timer.scheduledTimer(withTimeInterval: 0.01, repeats: true) { [weak self] _ in 
    m_log.requestLog{ data in
        self?.consumeLog(log: data)
    }
}

您可能会在主线程上显式更新 UI

func addLog(msg: String) {
    DispatchQueue.main.async {
        m_logView.text += msg + "\n"
    }
}

笔记:

根据 Swift 命名约定命名变量lowerCamelCased例如mLogView


推荐阅读