我有一个关于在后台线程上调用UI API的问题。
我需要视图信息来保存视图,例如,view.center、view.transform、view.frame.width.
这个编码需要在后台线程上执行,而不是在主线程上执行。
因为这种编码逻辑的计算成本很高,所以它会影响对用户交互的响应(比如Apple Pencil输入(。
所以我关闭了主线程检测器,并在后台线程上调用UI API。
我不需要任何UI更新,只需要收集UIView、UITextView、CALayer的信息。
在这种情况下,在后台线程上调用UI API是否存在任何可能的问题?
有一些警告消息,但我在调试模式下找不到任何问题。
请就保存视图信息的正确方式给出任何建议。
谢谢。
func pendingSave(pending: Bool) {
if let save = self.pendingRequestSave {
save.cancel()
}
if !pending {
self.save(workItem: nil)
return
}
self.pendingRequestSave = DispatchWorkItem(qos: .userInitiated, flags: .enforceQoS) { [weak self] in
self?.save(workItem: self?.pendingRequestSave)
}
//savingQueue is serial DispatchQueue
DrawingViewController.savingQueue.asyncAfter(deadline: .now() + .seconds(1),
execute: self.pendingRequestSave!)
}
func save(workItem: DispatchWorkItem?) {
let encoder = JSONEncoder()
let jsonData = try! encoder.encode(self.canvasView)
if workItem == nil || !(workItem!.isCancelled) {
DispatchQueue.main.async {
MonthService.save(dateId: self.curMonthInfo, contents: jsonData)
}
}
}
[断言]不支持在主线程外使用UIKit视图定制API-setBackgroundColor:发送到>
请注意,不仅UI更新需要放在主线程中,所有UI getter和setter也需要从主线程调用,这就是为什么您会遇到这些问题。
为了以适当的方式解决这个问题,您需要将高计算成本的函数放在后台线程中,并且在调用任何UI getter/setter时,您需要单独将其放在主线程中。
建议您始终启用主线程检查器,因为它可以节省大量时间来指示逻辑中的问题(如果存在(。
例如:
var array = [String]()
//High computational block, use operation queue to create a thread
OperationQueue.init().addOperation {
for string in array{
//UI Getter/Setter, use main thread queue
OperationQueue.main.addOperation {
textLabel.text = string
}
}
}