7

私のルートコントローラーには、CMMotionManager

@property (strong, nonatomic) CMMotionManager *MManager;

そのゲッターでは、遅延インスタンス化を行います。コントローラーのビューが読み込まれると、このメソッドを呼び出します

- (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);
    }];
}

「Away we go」と表示され、NSLogすぐにアプリがクラッシュし、このスレッド ログが表示されます

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は間違った場所に置きましたか?

4

1 に答える 1

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 を別のスレッドに移動する必要があります。currentQueue次に、NSOperationQueue に ではなく を使用するように指示します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)

于 2013-11-19T23:28:21.893 に答える