swift - 使用 swift 使 DispatchQueue 异步崩溃
问题描述
您好,以下代码为我生成此异常,此应用程序连接到远程 node.js api 休息服务器并获取设置应用程序的值。这些值用于基于对 node.js 进行的其余调用构建自定义菜单 这些值通过返回调用验证 boolean 类型值 奇怪的是它会在线程上生成应用程序崩溃
错误:
Main Thread Checker: UI API called on a background thread: -..
2019-03-19 15:52:03.255375+0100 myapp[441:34081] [reports] Main Thread Checker: UI API called on a background thread: -[UIApplication delegate]
PID: 441, TID: 34081, Thread name: (none), Queue name: com.apple.root.user-interactive-qos, QoS: 33
Backtrace:
4 myapp 0x00000001005ca3ac $S5myapp8DatabaseC12GetServerURLSSyF + 112
5 myapp 0x00000001005c66a4 $S5myapp4JSONC15GetSingleString6Router10ValueArray10completionySS_SDySSypGySSctF + 608
6 myapp 0x0000000100617a08 $S5myapp9UserModelC16VerificaPermesso09TipologiaE010completionySS_ySSctFyycfU_ + 456
7 myapp 0x0000000100566510 $SIeg_IeyB_TR + 52
8 libdispatch.dylib 0x00000001017f7824 _dispatch_call_block_and_release + 24
9 libdispatch.dylib 0x00000001017f8dc8 _dispatch_client_callout + 16
10 libdispatch.dylib 0x000000010180a330 _dispatch_root_queue_drain + 716
11 libdispatch.dylib 0x000000010180abc8 _dispatch_worker_thread2 + 156
12 libsystem_pthread.dylib 0x000000018404d17c _pthread_wqthread + 472
13 libsystem_pthread.dylib 0x000000018404fcec start_wqthread + 4
代码:
DispatchQueue.main.async {
//Controllo permesso accesso cantieri
self.u = User()
//Controllo permesso accesso Clienti
self.u.VerificaPermesso(TipologiaPermesso: "clienti", completion: { result in
DispatchQueue.main.async {
if(result == "false") {
viewControllerList.remove(at: 4)
self.viewControllers = viewControllerList
}
}
});
//Controllo permesso accesso Articoli
self.u.VerificaPermesso(TipologiaPermesso: "articoli", completion: { result in
DispatchQueue.main.async {
if(result == "false") {
viewControllerList.remove(at: 2)
self.viewControllers = viewControllerList
}
}
});
//Controllo permesso accesso Magazzino
self.u.VerificaPermesso(TipologiaPermesso: "magazzino", completion: { result in
DispatchQueue.main.async {
if(result == "false") {
viewControllerList.remove(at: 5)
self.viewControllers = viewControllerList
}
}
});
self.u.VerificaPermesso(TipologiaPermesso: "cantieri", completion: { result in
DispatchQueue.main.async {
if(result == "false") {
viewControllerList.remove(at: 1)
self.viewControllers = viewControllerList
}
}
});
}
获取服务器网址代码:
func GetServerURL() -> String {
let appDelegate = UIApplication.shared.delegate as! AppDelegate
let context = appDelegate.persistentContainer.viewContext
let request = NSFetchRequest<NSFetchRequestResult>(entityName: "Setup")
request.returnsObjectsAsFaults = false;
do {
let result = try context.fetch(request)
if result.count > 0
{
for result in result as! [NSManagedObject] {
if let server = result.value(forKey: "server")as? String
{
self.serverSet = server
}
if let port = result.value(forKey: "port") as? Int32
{
self.portSet = "\(port)"
}
}
}
}
catch {
print("Errore caricamento Parametri DB \(error)")
}
var ret = "\(serverSet):\(portSet)"
if(serverSet == "" || portSet == "") {
ret = ""
}
return ret
}
解决方案
根据您内部的崩溃日志,myapp.Database.GetServerURL
您尝试访问UIApplication.shared.delegate
哪个是 UIKit api,应该在主线程上执行。
可能的解决方案:
- 将此调用包装在
DispatchQueue.main.sync { ... }
.
这将解决您的错误,但代码异味和设计错误将继续存在,并可能在未来再次打击您 - 将此代码从
AppDelegate
模型依赖层移动。
由于它是与数据库相关的调用,请考虑将其移动到可能是单例的单独数据库服务中(DB 是可能使用单例的好例子)
推荐阅读
- reactjs - Lerna + Styled Components monorepo 无效的钩子
- c++ - 制作对象的多个版本
- python-3.x - Gmail Pubsub - 无限推送通知
- java - 如何在 MVC Spring Controller 中的两个端点之间传递数据
- reactjs - 如何将数据传递到不同的屏幕
- python - 在不使用路径的情况下将图像导入 pygame
- c# - Host Header 将导致 Puppeteer 中的 Invalid Argument 错误
- reactjs - 期望在箭头函数中返回一个值 - useEffect
- mysql - 如何通过 id 在 MySQL 中的 json 整数数组列中获取相关项目
- node.js - AWS LAMBDA S3 Glacier - 如果 S3 对象的存储类在 Glacier 中,如何检索它