在控制器内调用startDeviceMotionUpdatesToQueue时,我得到了OSSpinLockLock

时间:2013-10-24 15:38:59

标签: ios objective-c core-motion

在我的根控制器中,我有一个CMMotionManager

的属性
@property (strong, nonatomic) CMMotionManager *MManager;

在它的getter中我做懒惰的实例化。当控制器的视图加载时,我调用此方法

- (void)reloadAccelerometer {
    NSLog(@"Away we go");
    self.MManager.deviceMotionUpdateInterval = 10.0/60.0;
    [self.MManager startDeviceMotionUpdatesToQueue:self.queue withHandler:^(CMDeviceMotion *motion, NSError *error) {
        NSLog(@"Y values is: %f", motion.userAcceleration.y);
    }];
}

我在NSLog中看到“Away we go”,然后应用程序立即崩溃,我得到了这个帖子日志

libsystem_platform.dylib`spin_lock$VARIANT$mp:
0x39a87814:  movs   r1, #1

libsystem_platform.dylib`OSSpinLockLock$VARIANT$mp + 2:
0x39a87816:  ldrex  r2, [r0]
0x39a8781a:  cmp    r2, #0
0x39a8781c:  it     ne
0x39a8781e:  bne.w  0x39a893ec                ; _OSSpinLockLockSlow$shim
0x39a87822:  strex  r2, r1, [r0]
0x39a87826:  cmp    r2, #0
0x39a87828:  bne    0x39a87816                ; OSSpinLockLock$VARIANT$mp + 2
0x39a8782a:  dmb    ish
0x39a8782e:  bx     lr

我的错是什么?我把reloadAccelerometer放在了错误的地方吗?

1 个答案:

答案 0 :(得分:7)

我试图在我的iOS应用程序中做类似的事情并花费永远试图弄清楚崩溃的原因是什么。这是一个非常神秘(而且讨厌)的例外。在阅读OSSpinLock线程/队列管理问题有关的崩溃报告后,我最终弄明白了。

NSOperationQueue是罪魁祸首。您的代码没有显示您创建NSOperationQueue的方式,但我认为它是这样的:

NSOperationQueue *aQueue = [[NSOperationQueue alloc] init]; // Do NOT do this
[self.MManager startDeviceMotionUpdatesToQueue:aQueue withHandler:^(CMDeviceMotion *motion, NSError *error) {
    NSLog(@"Y values is: %f", motion.userAcceleration.y);
}];

事实证明,使用NSOperationQueue的方式。那个aQueue对象是崩溃的原因。

要正确设置操作队列并避免崩溃,您应该将CMMotionManager移动到其他线程。然后告诉NSOperationQueue使用 currentQueue ,而不是mainQueue。 Apple建议不要在mainQueue上运行,但如果您的应用当前正在主队列中运行,那么我看不到currentQueue有何不同。我尝试使用GCD将下面的代码移动到不同的队列,但是没有调用任何代码。

以下是您的最终代码应该是什么样的:

// Check if Motion / Location services are available
if (motionManager.deviceMotionAvailable == YES && motionManager.accelerometerAvailable == YES) {
    NSLog(@"Away we go");
    self.MManager.deviceMotionUpdateInterval = 10.0/60.0;
    [self.MManager startDeviceMotionUpdatesToQueue:[NSOperationQueue currentQueue] withHandler:^(CMDeviceMotion *motion, NSError *error) {
        NSLog(@"Y values is: %f", motion.userAcceleration.y);
     }];
} else {
    // Motion / Accelerometer services unavailable
}

我还应该注意到CMMotionManager属性(据我所知)的创建与(strong, nonatomic)一致。