在调用stopDeviceMotionUpdates之后引发iOS CoreMotion.MotionThread EXC_BAD_ACCESS

问题描述

我有一个使用CoreMotion监视设备姿态的视图控制器。

以下是在调用startDeviceMotionUpdates()时使用的处理程序:

/**
     * Receives device motion updates from Core Motion and uses the attitude of the device to update
     * the position of the attitude tracker inside the bubble level view.
     */
    private func handleAttitude(deviceMotion: CMDeviceMotion?,error: Error?) {
        guard let attitude = deviceMotion?.attitude else {
            GLog.Error(message: "Could not get device attitude.")
            return
        }
        
        // Calculate the current attitude vector
        let roll = attitude.roll
        let pitch = attitude.pitch - optimalAngle
        let magnitude = sqrt(roll * roll + pitch * pitch)
        
        // Drawing can only happen on the main thread
        dispatchQueue.main.async {
            [weak self] in
            
            guard let weakSelf = self else {
                GLog.Log("Could not get weak self")
                return
            }
            // Move the bubble in the attitude tracker to match the current attitude
            weakSelf.bubblePosX.constant = CGFloat(roll * weakSelf.attitudeScalar)
            weakSelf.bubblePosY.constant = CGFloat(pitch * weakSelf.attitudeScalar)
            
            // Set the border color based on the current attitude.
            if magnitude < weakSelf.yellowThreshold {
                weakSelf.attitudeView.layer.borderColor = weakSelf.green.cgColor
            } else if magnitude < weakSelf.redThreshold {
                weakSelf.attitudeView.layer.borderColor = weakSelf.yellow.cgColor
            } else {
                weakSelf.attitudeView.layer.borderColor = weakSelf.red.cgColor
            }
            
            // Do the actual drawing
            weakSelf.view.layoutIfNeeded()
        }
    }

添加了[弱自我],以查看它是否可以解决问题,但不能解决问题。此崩溃不容易重现。

当我完成使用CoreMotion的VC时,我在VC的viewWilldisappear()方法调用stopDeviceMotionUpdates()。该VC是应用程序中唯一导入CoreMotion的类。

但是,当我到达下一个VC时,偶尔会看到EXC_BAD_ACCESS被抛出到了一个co.apple.CoreMotion.MotionThread。

MotionThread backtrace

有人知道为什么CoreMotion在使用了它的VC被关闭后会生成一个线程吗?我已验证崩溃发生时VC不再在内存中。是的,我正在处理的两个VC是模态呈现的。

我已经检查了内存图,当崩溃发生时,正在报告这些CoreMotion对象:

enter image description here

并且:

enter image description here

我不知道在释放了CoreMotionManager实例之后,那些对象是否仍然应该在内存中。根据内存图,内存中没有CoreMotionManager的实例。

导入CoreMotion的VC也导入ARKit。不确定CoreMotion和ARKit之间是否存在某种疯狂的交互作用。

主线程和MotionThread(14)之间似乎确实发生了某些事情:

expanded stack trace

我不确定要如何处理主线程堆栈跟踪。

有时候,关闭CoreMotion VC时,我注意到它释放所使用的内存存在滞后。释放总是最终发生。

感谢任何可以提供帮助的人!

解决方法

您是否将函数handleAttitude传递给startDeviceMotionUpdates

startDeviceMotionUpdates(to:someQueue,withHandler:handleAttitude)

这将在VC和CMMotionManager之间建立保留周期

尝试

singletonMM.startDeviceMotionUpdates(to:someQueue) { [weak self] motion,error in
    self?.handleAttitude(motion,error)
}

为避免强烈引用您的VC。

,

我们有一个ARSCNView成员。当我们解散使用sceneView成员的VC时,我们没有调用sceneView.session.pause()。一行代码。就是这样。