我刚刚启动了一个新的Xcode ARKit项目,并在物理设备上运行了它,但是在控制台中,我得到了以下输出:
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
我对你们的问题是为什么我要得到这个输出?到底是什么意思?
非常感谢您的帮助。
答案 0 :(得分:1)
(您当然可以禁用检查器,但有时它会有所帮助。为此检查https://stackoverflow.com/a/45689250/7183675。)
错误在Apple框架内部,所以我发现只能解决的方法是将UIApplication类子类化,并以此方式检查主线程上的应用程序状态:
1)在这些行中添加main.swift文件(此名称确实很重要!)
import UIKit
UIApplicationMain(
CommandLine.argc,
CommandLine.unsafeArgv,
NSStringFromClass(MyApplicationClass.self),
NSStringFromClass(MyDelegateClass.self)
)
2)如果@UIApplicationMain
在MyDelegateClass
中,或者由于多个入口点而导致项目无法编译,则将其删除。
3)在MyApplicationClass.swift中添加以下内容:
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,因此不会发生问题。
嗯,还有一个问题。如果CMMotionManager是从主线程初始化的,则将阻塞主线程并等待UIApplication.State。那意味着僵局。在这种情况下,您无法设置信号量。返回可信状态以避免死锁的唯一方法是通过以下方式实现应用程序状态:
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
}
}
}
我个人不喜欢上一个解决方案,但是我找不到其他解决方法