gpt4 book ai didi

ios - 异步调用时 UI 元素在 Segue 后缺少文本

转载 作者:可可西里 更新时间:2023-11-01 02:05:37 25 4
gpt4 key购买 nike

今天,在为大学类(class)构建网络分析应用程序时,我遇到了一个有趣的难题。从异步 DispatchQueue 调用 performSegue 会使目标 View Controller 中某些 UI 的文本变为空白。按钮、标签等。就好像它们的文本属性设置为空字符串一样。

我会进一步解释。

我有一个名为 Globals 的自定义 Swift 类,它用于存放(显然)需要在整个应用程序范围内读写的全局变量。

我有一个 UIViewController 作为我的应用程序的加载屏幕。

我有一个在加载屏幕完成时加载的 UIViewController

我有一个 URLSession 在一个单独的 Swift 类中运行,它被加载屏幕 View Controller 调用。它的目的是下载一个已知大小的小文件,并通过测量下载它所花费的时间来提供速度估计。这是该函数:

func testSpeed() {

Globals.shared.dlStartTime = Date()

if Globals.shared.currentSSID == "" {
Globals.shared.bandwidth = 0
Globals.shared.DownComplete = true
} else {

let url = URL(string: "[EXAMPLE]")
let session = URLSession(configuration: URLSessionConfiguration.default, delegate: self, delegateQueue: nil)
let task = session.downloadTask(with: url!)

task.resume()
}
}

public func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didWriteData bytesWritten: Int64, totalBytesWritten: Int64, totalBytesExpectedToWrite: Int64) {

Globals.shared.dlFileSize = (Double(totalBytesExpectedToWrite) * 8) / 1000

let progress = (Double(totalBytesWritten) / Double(totalBytesExpectedToWrite)) * 100.0

Globals.shared.dlprogress = Int(progress)
}

public func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didFinishDownloadingTo location: URL) {

let elapsed = Double( Date().timeIntervalSince(Globals.shared.dlStartTime))
Globals.shared.bandwidth = Int(Globals.shared.dlFileSize / elapsed)
Globals.shared.DownComplete = true
Globals.shared.dataUse! += (Globals.shared.dlFileSize! / 8000)
}

如您所见,URLSession 使用委托(delegate) URLSessionDelegateURLSessionDownloadDelegate 将下载进度传递到加载屏幕,这让用户知道事情的进展情况。

您还可以看到,有一个全局 bool 变量 DownComplete,它让应用程序的其余部分知道进程何时完成。

返回加载屏幕。有一个名为 progressLabel 的完成标签以及一个名为 MainProgress 的自定义径向进度 View 。这是代码:

override func viewDidAppear(_ animated: Bool) {

[...]

Networking().testSpeed()
updateProgress()
}

func updateProgress() {
DispatchQueue.global().async {
while Globals.shared.DownComplete == false {
DispatchQueue.main.sync {
self.progressLabel.text = String(Globals.shared.dlprogress) + "%"
self.MainProgress.animate(fromAngle: self.MainProgress.angle, toAngle: Double(Globals.shared.dlprogress)
}
}
self.performSegue(withIdentifier: "LoadCompleteSegue", sender: self)
}
}

我们的想法是运行一个 while 循环,等待该过程完成后再加载下一个 View Controller 。

但是为了不阻塞主线程,while 循环必须异步运行。

...但是要正确更新 UI,这些调用必须在同步块(synchronized block)中进行。

......但是为了不完全跳过该过程,performSegue 必须在与 while 循环相同的线程中完成。我认为这就是导致我出现问题的原因。

下面是下一个 View Controller 的屏幕截图,其中我用红框标出了应该文本的区域。因为令我困惑的是它不会影响 所有 UI 元素,只会影响几个。

Screenshot: Missing Elements

编辑:

我知道代码不是最干净的,但这是我的“testgrounds”Git 分支。请耐心等待。

最佳答案

您必须在主队列上执行 segue。如果您在 while 循环运行后分派(dispatch)它,它应该可以正常工作。尝试将 updateProgress() 函数更新为以下内容:

func updateProgress() {
DispatchQueue.global().async {
while Globals.shared.DownComplete == false {
DispatchQueue.main.sync {
self.progressLabel.text = String(Globals.shared.dlprogress) + "%"
self.MainProgress.animate(fromAngle: self.MainProgress.angle, toAngle: Double(Globals.shared.dlprogress)
}
}
DispatchQueue.main.async {
self.performSegue(withIdentifier: "LoadCompleteSegue", sender: self)
}
}
}

关于ios - 异步调用时 UI 元素在 Segue 后缺少文本,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43037857/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com