- android - RelativeLayout 背景可绘制重叠内容
- android - 如何链接 cpufeatures lib 以获取 native android 库?
- java - OnItemClickListener 不起作用,但 OnLongItemClickListener 在自定义 ListView 中起作用
- java - Android 文件转字符串
今天,在为大学类(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) URLSessionDelegate
和 URLSessionDownloadDelegate
将下载进度传递到加载屏幕,这让用户知道事情的进展情况。
您还可以看到,有一个全局 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 元素,只会影响几个。
编辑:
我知道代码不是最干净的,但这是我的“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/
我一整天都遇到同样的错误,我知道这是在说 Storyboard 中没有识别出 segue,但确实如此。以下是我认为相关的代码:1.为 segue 发出信号的按钮的 IBAction。 -(IBActi
我有一个从 A View Controller 到 B View Controller 的 unwind segue。 在B中做了一个网络操作,操作完成后,响应会显示在A View Controlle
我正在创建一个应用程序,家长可以在其中登录并查看有关其本地托儿中心的信息。但是,为登录运行 View Controller 的代码无法正常工作。一旦用户按下登录按钮,我希望我的代码使用标识符“Show
刚刚遇到一个奇怪的问题。我有一个启动画面,它自动使用自定义 segue (fade-to-segue) 转到主页 ViewController。自定义 segue 工作正常,但一旦实现,我在主页上的其
以编程方式创建的 segue 在 performSegueWithIdentifier: 上使应用程序崩溃,不过我真的不想使用 Storyboard。 - (void)viewDidLoad { [s
我想我一定在这里遗漏了一些简单的东西,但我不知道它是什么。 我必须支持来自同一个 View Controller 的多个 segue,所以我很自然地想使用 segue 标识符。我的代码由于某种原因无法
当用户在警告时点击“确定”按钮时,我如何才能将用户带到自定义 View Controller ? 我有一个主 Controller -> 导航 Controller -> 第二个 View Contr
在 TableView Controller 中,我试图获取在我继续之前选择的行的索引(最终将传递此信息以准备继续)。我已经实现了这个功能: var selectedQuestionCell: Ind
我正在 Xamarin Studio 中开发一个应用程序(所以它是 C#),它有一个包含多个 TextField 的表单,我想在 segue 之前验证整个屏幕> 到下一个屏幕执行。单击按钮时,它正在使
我有一个带有标识符的 segue。 当我按下函数 shouldPerformSegueWithIdentifier 中的按钮时,我得到一个空标识符 什么会导致这样的问题?我设置错了什么? 这是我的代码
我有一个奇怪的问题。我在 Storyboard中创建了 2 个 View Controller :testSegueViewcontroller 和 nextPageViewController。 t
我下面的代码试图将一个值从 twoviewcontroller 转移到 View Controller 。 segue 正在工作,我可以从 View Controller 转到 View Contro
我正在尝试使用自定义segue,当单击按钮时,它会使 View 向右或向左“滚动”。我添加了一个如下所示的自定义类 class horizontalSegue : UIStoryboardSegue
我有一个带有 Root View Controller 的 UINavigationController。我的 UINavigationController 也设置为我的应用程序的 Initial V
您好,我正在尝试使用 prepare for segue 方法执行一个 segue。我在关注这个问题 this但我无法成功注册。当我单击注册按钮时,它所做的只是注册用户并停在那里。我从 View Co
当 Storyboard上有一个按钮连接退出时,我了解如何使用展开转场。但是在我的应用程序中,我使用推送转场从 TableViewController 转到 ViewController。所以我的导航
我要实现的目标的背景: MainViewController 呈现 TableVC。我将点击一个单元格以显示 DetailVC。能够通过 TableVC 或 DetailVC 上导航栏上的 doneB
在我的 Storyboard中,模态转场将用户带到登录屏幕(从主屏幕)。然后,我从注册屏幕添加了一个 PUSH segue 到下一个屏幕(创建配置文件),该屏幕嵌入在导航 Controller 中(创
我有大约 6 个 segue 在 prepareForSegue 方法中执行相同的操作,但是,我想为我的 unwind segue 跳过此操作,但我无法弄清楚如何确定传递的 segue 是 unwin
因此,我开始在XCode 4.3.2中使用 Storyboard 。我从Master-Detail应用程序(iPad的拆分 View 应用程序)开始。在详细信息 View (名为DetailVC)中,
我是一名优秀的程序员,十分优秀!