【发布时间】:2021-12-04 15:19:10
【问题描述】:
Swift 5:我无法及时更新我的 UITableView(同时使用 DispatchQueue.global().sync 和 DispatchQueue.main.async
简而言之:
- 我有一个简单的
for index in 1…20循环可以做一些“事情”。 - 在 20 次迭代中的每一次结束时,我都会将一个新元素附加到作为我的 UITableView 的数据源的数组中。
- 我只是想让 UITableView 在开始下一次循环迭代之前更新显示。
- 真的有这么多要问的吗?哈哈
我试过把所有的“工作”放在后台线程上,我什至用QoSClass.utility创建了一个线程,不管我做什么......它完全忽略了所有出现的DispatchQueue.main.async,直到整个函数完成.
我可以毫无问题地完成我的代码需要完成的工作。在这一点上,我面临的挑战是控制事情发生的顺序并让显示更新(并保持对用户的响应,目前不会这样做)。
编辑/更新:
使用下面的答案......如果我使用 .async 我会得到我想要的及时更新但我没有得到按顺序 1、2 的索引结果, 3 ... 20. 如果我使用 .sync 我得到了我想要的订单但没有更新。 如何让我的循环按顺序执行并在每个循环中显示一次 GET UPDATES?
我对这里的线程非常陌生,所以请慢慢输入。谢谢!
这是我非常精简的代码:
//
// ValidateViewController.swift
// MySpecialProject
//
// Created by Jim Termini on 10/16/21.
//
import UIKit
import PDFKit
import UniformTypeIdentifiers
import CoreData
class ValidateViewController: UIViewController, PDFViewDelegate {
@IBOutlet weak var tableView: UITableView!
var statuses: [ValidationStatus] = []
//????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
//???? START HERE: ViewDidLoad
//????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
override func viewDidLoad() {
super.viewDidLoad()
statuses = createStatusArray()
tableView.delegate = self
tableView.dataSource = self
}
//????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
//???? Button Pressed — Start Validating the Document!!
//????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
@IBAction func startValidatIn(_ sender: Any) {
print("????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????")
print("????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????")
theMainThing()
print("????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????")
print("????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????")
}
//????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
//???? theMainThing function called when button pushed.
//????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
func theMainThing() {
print("????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????")
print(pickedDocSourceFPnFURL ?? "No File Picked")
let openResults = openFile(pdfURLToSearch: pickedDocSourceFPnFURL!)
originalPDFDocument = openResults.0
metaPDFModifiedDate = openResults.1
var unaccountedPageCount = orginalDocumentPageCount
// Keep track of the total number of Forms found in the Document
var theFormCount = 0
let JimmyQoS: DispatchQoS.QoSClass = DispatchQoS.QoSClass.utility
let JimmysQue: DispatchQueue = DispatchQueue.global(qos: JimmyQoS)
var countOfFormsOfThisPageLength: Int = 0
var dummyVar: Int = 0
for index in 1...20 {
JimmysQue.sync {
print("????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????")
if index == 6 {
//
// Do special case stuff when index = 6
//
} else if index == 1 {
//
// Do special case stuff when index = 6
//
} else {
//
// Do regular case stuff when index = 2 – 5, 7 – 20.
//
}
print("????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????")
print("The NEXT Line is \"DispatchQueue.main.async\" SHOULD see GREEN row NEXT!!")
DispatchQueue.main.async {
print("????????????\(Date())????????????????????????????????????????????????????????????????????????????????????????????????????????????")
print("Here I am ... INSIDE the main thread async.")
if countOfFormsOfThisPageLength > 0 {
let term = (countOfFormsOfThisPageLength > 1) ? "forms" : "form"
self.statuses.append((ValidationStatus(image: StatusIcon.allGood, title: "Identified \(countOfFormsOfThisPageLength) \(term) of \(index) pages each.", details: "Unaccounted for Pages: \(dummyVar) of \(self.orginalDocumentPageCount)")))
self.tableView.reloadData()
self.tableView.setNeedsDisplay()
}
print("This SHOULD be causing my display to update.")
print("????????????\(Date())????????????????????????????????????????????????????????????????????????????????????????????????????????????")
}
print("????????????\(Date())????????????????????????????????????????????????????????????????????????????????????????????????????????????")
print("Here I am ... about to sleep the global (background) thread for 5 seconds to ensure the TableView is updated and displayed properly.")
sleep(5)
print("And here I am ... 5 seconds later ... still no UIViewTable Update :-(")
print("????????????\(Date())????????????????????????????????????????????????????????????????????????????????????????????????????????????")
}
}
}
}
这里是发生和应该发生的事情的演练……
- 我按下“开始验证”按钮
- 两排紫/绿印花✅
-
theMainThing()函数被调用 ✅ - 一排红/黄印花✅
-
for index in 1…20循环开始✅- 黄线打印在每个循环的开始✅
- 我的处理确实做了它应该做的事情✅
- 在
DispatchQueue.main.async块之前打印一条红线应该以更高的优先级执行更新UITableView。 ✅ - 主 (UI) 线程应该启动并且 ❌
- 打印绿色行 ❌
- 更新 UITableView/display ❌
- 打印第二个绿色行 ❌
- 给 UI 更新时间……我
- 打印紫色行✅
- 让后台队列休眠 5 秒 ✅
- 再打印一个紫色行✅
这是我的 ACTUAL 控制台输出:
绿线,来自高优先级主线程,直到for index in 1…20循环完成后+theMainThing()函数完成后+startValidatIn(_ sender: Any)函数完成后才执行‼️
????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
The NEXT Line is "DispatchQueue.main.async" SHOULD see GREEN row NEXT!!
????????????2021-10-17 02:34:21 +0000????????????????????????????????????????????????????????????????????????????????????????????????????????????
Here I am ... about to sleep the global (background) thread for 5 seconds
to ensure the TableView is updated and displayed properly.
And here I am ... 5 seconds later ... still no UIViewTable Update :-(
????????????2021-10-17 02:34:26 +0000????????????????????????????????????????????????????????????????????????????????????????????????????????????
-------------------------
18 Duplicate Sets Omitted
-------------------------
????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
The NEXT Line is "DispatchQueue.main.async" SHOULD see GREEN row NEXT!!
????????????2021-10-17 02:34:26 +0000????????????????????????????????????????????????????????????????????????????????????????????????????????????
Here I am ... about to sleep the global (background) thread for 5 seconds
to ensure the TableView is updated and displayed properly.
And here I am ... 5 seconds later ... still no UIViewTable Update :-(
????????????2021-10-17 02:34:31 +0000????????????????????????????????????????????????????????????????????????????????????????????????????????????
????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
????????????2021-10-17 02:46:34 +0000????????????????????????????????????????????????????????????????????????????????????????????????????????????
Here I am ... INSIDE the main thread async.
This SHOULD be causing my display to update.
????????????2021-10-17 02:46:34 +0000????????????????????????????????????????????????????????????????????????????????????????????????????????????
????????????2021-10-17 02:46:34 +0000????????????????????????????????????????????????????????????????????????????????????????????????????????????
Here I am ... INSIDE the main thread async.
This SHOULD be causing my display to update.
????????????2021-10-17 02:46:34 +0000????????????????????????????????????????????????????????????????????????????????????????????????????????????
这是我的控制台输出应该是:
每个红线之后应该是来自高优先级主 UI 线程的绿线。
????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
The NEXT Line is "DispatchQueue.main.async" SHOULD see GREEN row NEXT!!
????????????2021-10-17 02:46:34 +0000????????????????????????????????????????????????????????????????????????????????????????????????????????????
Here I am ... INSIDE the main thread async.
This SHOULD be causing my display to update.
????????????2021-10-17 02:46:34 +0000????????????????????????????????????????????????????????????????????????????????????????????????????????????
????????????2021-10-17 02:34:21 +0000????????????????????????????????????????????????????????????????????????????????????????????????????????????
Here I am ... about to sleep the global (background) thread for 5 seconds
to ensure the TableView is updated and displayed properly.
And here I am ... 5 seconds later ... still no UIViewTable Update :-(
????????????2021-10-17 02:34:26 +0000????????????????????????????????????????????????????????????????????????????????????????????????????????????
????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
The NEXT Line is "DispatchQueue.main.async" SHOULD see GREEN row NEXT!!
????????????2021-10-17 02:46:34 +0000????????????????????????????????????????????????????????????????????????????????????????????????????????????
Here I am ... INSIDE the main thread async.
This SHOULD be causing my display to update.
????????????2021-10-17 02:46:34 +0000????????????????????????????????????????????????????????????????????????????????????????????????????????????
????????????2021-10-17 02:34:26 +0000????????????????????????????????????????????????????????????????????????????????????????????????????????????
Here I am ... about to sleep the global (background) thread for 5 seconds
to ensure the TableView is updated and displayed properly.
And here I am ... 5 seconds later ... still no UIViewTable Update :-(
????????????2021-10-17 02:34:31 +0000????????????????????????????????????????????????????????????????????????????????????????????????????????????
????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
【问题讨论】:
-
如果你真的不了解线程,并且如果你可以将你的应用程序限制在 iOS 15 及更高版本,那么使用美妙的新 async/await 你会很多更快乐东西。
标签: swift multithreading asynchronous