ARKit模板Xcode项目Main Thread Checker日志控制台 [英] ARKit template Xcode project Main Thread Checker log console
问题描述
我刚刚启动了一个新的Xcode ARKit项目,并在物理设备上运行了它,但是在控制台中,我得到了以下输出:
I just started a new Xcode ARKit project and ran it on a physical device but in the console I'm getting this output:
Main Thread Checker: UI API called on a background thread: -[UIApplication applicationState]
PID: 4865, TID: 2042694, Thread name: com.apple.CoreMotion.MotionThread, Queue name: com.apple.root.default-qos.overcommit, QoS: 0
Backtrace:
4 libobjc.A.dylib 0x00000001d7477894 <redacted> + 56
5 CoreMotion 0x00000001ddcf4760 CoreMotion + 304992
6 CoreMotion 0x00000001ddcf4c94 CoreMotion + 306324
7 CoreMotion 0x00000001ddcf4ba4 CoreMotion + 306084
8 CoreMotion 0x00000001ddd26384 CoreMotion + 508804
9 CoreMotion 0x00000001ddd263e4 CoreMotion + 508900
10 CoreFoundation 0x00000001d820d4d8 <redacted> + 28
11 CoreFoundation 0x00000001d820cdbc <redacted> + 276
12 CoreFoundation 0x00000001d82080c0 <redacted> + 2324
13 CoreFoundation 0x00000001d8207494 CFRunLoopRunSpecific + 452
14 CoreFoundation 0x00000001d82081f8 CFRunLoopRun + 84
15 CoreMotion 0x00000001ddd25d1c CoreMotion + 507164
16 libsystem_pthread.dylib 0x00000001d7e829c8 <redacted> + 132
17 libsystem_pthread.dylib 0x00000001d7e82924 _pthread_start + 52
18 libsystem_pthread.dylib 0x00000001d7e8addc thread_start + 4
2018-11-19 09:21:42.623520-0800 MyFirstARKitApp[4865:2042694] [reports] Main Thread Checker: UI API called on a background thread: -[UIApplication applicationState]
PID: 4865, TID: 2042694, Thread name: com.apple.CoreMotion.MotionThread, Queue name: com.apple.root.default-qos.overcommit, QoS: 0
Backtrace:
4 libobjc.A.dylib 0x00000001d7477894 <redacted> + 56
5 CoreMotion 0x00000001ddcf4760 CoreMotion + 304992
6 CoreMotion 0x00000001ddcf4c94 CoreMotion + 306324
7 CoreMotion 0x00000001ddcf4ba4 CoreMotion + 306084
8 CoreMotion 0x00000001ddd26384 CoreMotion + 508804
9 CoreMotion 0x00000001ddd263e4 CoreMotion + 508900
10 CoreFoundation 0x00000001d820d4d8 <redacted> + 28
11 CoreFoundation 0x00000001d820cdbc <redacted> + 276
12 CoreFoundation 0x00000001d82080c0 <redacted> + 2324
13 CoreFoundation 0x00000001d8207494 CFRunLoopRunSpecific + 452
14 CoreFoundation 0x00000001d82081f8 CFRunLoopRun + 84
15 CoreMotion 0x00000001ddd25d1c CoreMotion + 507164
16 libsystem_pthread.dylib 0x00000001d7e829c8 <redacted> + 132
17 libsystem_pthread.dylib 0x00000001d7e82924 _pthread_start + 52
18 libsystem_pthread.dylib 0x00000001d7e8addc thread_start + 4
我对你们的问题是,为什么我要得到这个输出?到底是什么意思?
My question to you guys is why I'm getting this output? and what it means ?
非常感谢您的帮助.
推荐答案
(Of course you can disable checker, but sometimes it can be helpful. Check https://stackoverflow.com/a/45689250/7183675 for this.)
错误是在Apple框架内部,所以我发现只能解决的方法是将UIApplication类子类化,并以此方式检查主线程上的应用程序状态:
Error is inside Apple framework, so only way I found do work around it was subclassing UIApplication class and check application state on main thread this way:
1)在这些行中添加main.swift文件(此名称确实很重要!)
1) Add main.swift file (this name is really important!) with these lines
import UIKit
UIApplicationMain(
CommandLine.argc,
CommandLine.unsafeArgv,
NSStringFromClass(MyApplicationClass.self),
NSStringFromClass(MyDelegateClass.self)
)
2)如果@UIApplicationMain
在其中,或者由于多个入口点而导致项目无法编译,则将其从MyDelegateClass
中删除
2) Remove @UIApplicationMain
from MyDelegateClass
if it was there or project wont compile because of multiple entry points
3)在MyApplicationClass.swift中添加以下内容:
3) In MyApplicationClass.swift add this:
import UIKit
class MyApplicationClass: UIApplication {
let semaphore = DispatchSemaphore(value: 0)
override var applicationState: UIApplication.State {
if Thread.current == Thread.main {
return super.applicationState
}
var toReturn = UIApplication.State.inactive
DispatchQueue.main.async { [weak self] in
guard let self = self else {return}
toReturn = self.superAppState()
self.semaphore.signal()
}
semaphore.wait()
return toReturn
}
private func superAppState() -> UIApplication.State {
return super.applicationState
}
}
现在您正在主线程上调用UIApplication.applicationState,因此不会发生问题.
Now you are calling UIApplication.applicationState on main thread, so issue won't occur.
嗯,还有一个问题.如果CMMotionManager是从主线程初始化的,则将阻塞主线程并等待UIApplication.State.那意味着僵局.在这种情况下,您无法设置信号量.返回可信状态以避免死锁的唯一方法是通过以下方式实现应用程序状态:
Well, there is one more issue. If CMMotionManager is initialized from main thread then if will block main thread and wait for UIApplication.State. That means deadlock. In this case you can't set your semaphore. Only way to return credible state avoiding deadlock would be implementing application state this way:
4)
import UIKit
class MyApplicationClass: UIApplication {
private static var configured = false
private var state = UIApplication.State.inactive
override var applicationState: UIApplication.State {
if !MyApplicationClass.configured {
MyApplicationClass.configured = true
NotificationCenter.default.addObserver(self, selector: #selector(setStatus(_:)), name: UIApplication.didBecomeActiveNotification, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(setStatus(_:)), name: UIApplication.willResignActiveNotification, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(setStatus(_:)), name: UIApplication.willEnterForegroundNotification, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(setStatus(_:)), name: UIApplication.didEnterBackgroundNotification, object: nil)
}
if Thread.current == Thread.main {
return super.applicationState
}
return state
}
@objc func setStatus(_ notif: Notification) {
switch notif.name {
case UIApplication.didBecomeActiveNotification:
state = .active
case UIApplication.willResignActiveNotification:
state = .inactive
case UIApplication.willEnterForegroundNotification:
state = .background
case UIApplication.didEnterBackgroundNotification:
state = .background
default:
state = .inactive
}
}
}
我个人不喜欢上一个解决方案,但找不到其他解决方法
Personally I don't like last solution, but I wasn't able to find another workaround
这篇关于ARKit模板Xcode项目Main Thread Checker日志控制台的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!