【问题标题】:Swift main loop for updating a view用于更新视图的 Swift 主循环
【发布时间】:2020-02-19 08:21:56
【问题描述】:

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

但是,我得到的只是一个空白屏幕,其中包含以下代码:

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,但它在哪里?

【问题讨论】:

  • 尝试调试时看到了什么?你试过可视化调试器吗?
  • @Lu_ 它只是永远卡在while循环中,一遍又一遍地调用requestLog
  • 所以请记住第一件事,您应该将 UI 更新放在主线程上,其次,当您在文本视图中添加空行时,您希望在屏幕上看到什么? :D
  • @Lu_ 嗯,你是说我现在在单独的线程上做事吗?如果我在 viewDidLoad() 中调用 addLog(text),我确实会在屏幕上看到文本。 “空行”是什么意思?
  • 您的应用程序卡住了,因为您正在运行一个永无止境的无限循环并且您的应用程序被冻结。应该有行数限制。

标签: ios swift model-view-controller


【解决方案1】:

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

使用异步工作的Timer

替换

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

【讨论】:

  • 谢谢。是的。在看到这个答案之前,我才意识到这一点并自己用 Timer 实现了它。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-02-27
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多