在控制器内调用startDeviceMotionUpdatesToQueue时得到OSSpinLockLock [英] I get OSSpinLockLock when calling startDeviceMotionUpdatesToQueue inside a controller
问题描述
在我的根控制器中,我有一个CMMotionManager
In my root controller I have a property with the CMMotionManager
@property (strong, nonatomic) CMMotionManager *MManager;
在它的getter中,我进行了惰性实例化.当控制器的视图加载时,我调用此方法
In its getter I do lazy instantiation. When the controller's view loads, I call this method
- (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",然后应用立即崩溃,并且得到了该线程日志
I see "Away we go" in the NSLog
and then immediately the app crashes and I get this thread log
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
放在错误的位置了吗?
What's my mistake? Did i place reloadAccelerometer
in the wrong place?
推荐答案
我试图在我的iOS应用中做类似的事情,并花了永远来找出崩溃的原因.这是一个非常隐秘的(令人讨厌的)异常.在阅读完崩溃报告后,我终于弄清了这件事,该报告涉及OSSpinLock
与线程/队列管理问题有关.
I was trying to do something similar in my iOS app and spent forever trying to figure out what the cause of the crash was. This was a very cryptic (and pesky) exception. I eventually figured it out after reading through the crash reports that OSSpinLock
has to do with a thread / queue management issue.
NSOperationQueue
是这里的罪魁祸首.您的代码未显示您如何创建NSOperationQueue
,但是我认为它是这样的:
The NSOperationQueue
is the culprit here. Your code doesn't show how you were creating your NSOperationQueue
, but I assume it was something like this:
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
对象是导致崩溃的原因.
It turns out that this is not the way to use the NSOperationQueue
. That aQueue
object is the cause of the crash.
要正确设置操作队列并避免崩溃,应将CMMotionManager移至其他线程.然后告诉NSOperationQueue使用 currentQueue
,而不是mainQueue
.苹果建议不要在mainQueue
上运行它,但是,如果您的应用当前正在主队列中运行,那么我看不到currentQueue
有什么不同.我尝试使用GCD将下面的代码移到另一个队列中,但从未调用过任何代码.
To properly setup the operation queue and avoid a crash, you should move your CMMotionManager to a different thread. Then tell NSOperationQueue to use the currentQueue
, NOT the mainQueue
. Apple recommends that it is not run on the mainQueue
, however if your app is currently running in the main queue then I don't see how the currentQueue
is any different. I tried moving the code below to a different queue using GCD, but no code was ever called.
这是您最终代码的外观:
Here's what your final code should look like:
// 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)
是正确的.
I should also note that your creation of the CMMotionManager
property (to my knowledge) is correct with (strong, nonatomic)
.
这篇关于在控制器内调用startDeviceMotionUpdatesToQueue时得到OSSpinLockLock的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!