2013-10-24 26 views
6

içine startDeviceMotionUpdatesToQueue çağrılırken ben Tembel örnekleme yapmak onun gaz giderici olarak CMMotionManagerbenim kök denetleyicisi bir denetleyici

@property (strong, nonatomic) CMMotionManager *MManager; 

sahip bir mülkünüz OSSpinLockLock olsun. kontrolörün görünümü yükler, bu yöntem Sonra NSLog ve hemen uygulama çöker "dışarıda başlıyoruz" bakın

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

arayıp olsun Konuyu günlüğü

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 

benim hatam ne? reloadAccelerometer'u yanlış yere mi yerleştirdim?

cevap

6

iOS uygulamasında benzer bir şey yapmaya çalışıyordum ve 'un çökmesine neden olduğunu anlamaya çalışıyorum. Bu çok şifreli (ve sinir bozucu) bir istisna oldu. Sonunda OSSpinLockbir iş parçacığı/kuyruk yönetim sorunu ile ilgili olan çökme raporları okuduktan sonra anladım.

NSOperationQueue burada suçludur. Eğer senin NSOperationQueue oluştururken nasıl Kodunuz göstermez, ama böyle bir şey olduğunu varsayalım:

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

Bu değilNSOperationQueue kullanmak yoludur çıkıyor. Bu aQueue nesnesi, çökmenin nedenidir.

İşlem sırasını doğru şekilde kurmak ve bir çarpışmayı önlemek için CMMotionManager cihazınızı farklı bir iş parçacığına taşımanız gerekir. Sonra, NSOperationQueue öğesinin mainQueue numaralı currentQueue'u kullanmasını söyleyin. Apple, mainQueue'da çalıştırılmamasını önerir, ancak uygulamanız şu anda ana sırada çalışıyorsa, currentQueue'un nasıl farklı olduğunu göremiyorum. Aşağıdaki kodu GCD kullanarak farklı bir sıraya taşımayı denedim, ancak hiç kod çağrılmadı. Ben de (bildiğim kadarıyla) CMMotionManager mülkiyet senin eserin (strong, nonatomic) ile doğru olduğuna dikkat etmelidir

// 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 
} 

:

İşte böyle son kod görünmesi gerektiği.

+1

Vay, harika cevap! Teşekkürler RazorSharp :) –

İlgili konular