Royaume accédé à partir d'un thread incorrect

J'utilise la queue GCD série pour travailler avec le royaume. Les plantages d'application avec Realm accessed from incorrect thread exception de Realm accessed from incorrect thread lorsque GCD commence à changer de thread pour la queue. Est-il possible de lier un domaine donné avec un thread en utilisant l'API GCD?

Voici un exemple rapide

 self.realmQueue = dispatch_queue_create("db", DISPATCH_QUEUE_SERIAL); __block RLMRealm *realm = nil; dispatch_async(self.realmQueue, ^{ realm = [RLMRealm realmWithPath:[NSTemporaryDirectory() ssortingngByAppendingPathComponent:@"temp"]]; }); self.motionManager = [[CMMotionManager alloc] init]; self.motionManager.accelerometerUpdateInterval = 0.001; __block int i = 0; __block BOOL shouldBeginWriteTransaction = YES; [self.motionManager startAccelerometerUpdatesToQueue:[[NSOperationQueue alloc] init] withHandler:^(CMAccelerometerData *accelerometerData, NSError *error) { dispatch_async(self.realmQueue, ^{ if (shouldBeginWriteTransaction) { [realm beginWriteTransaction]; shouldBeginWriteTransaction = NO; } AccelerationEvent *event = [[AccelerationEvent alloc] init]; event.x = accelerometerData.acceleration.x; event.y = accelerometerData.acceleration.x; event.z = accelerometerData.acceleration.y; event.time = [NSDate date]; [realm addObject:event]; if (i % 1000) { dispatch_async(dispatch_get_main_queue(), ^{ self.xLabel.text = [NSSsortingng ssortingngWithFormat:@"%f", event.x]; self.yLabel.text = [NSSsortingng ssortingngWithFormat:@"%f", event.y]; self.zLabel.text = [NSSsortingng ssortingngWithFormat:@"%f", event.z]; }); } if (i % 10000 == 0) { NSDate *startDate = [NSDate date]; [realm commitWriteTransaction]; NSLog(@"save time: %f", [[NSDate date] timeIntervalSinceDate:startDate]); shouldBeginWriteTransaction = YES; } i++; }); }]; 

A partir des documents Realm : RLMRealm objects RLMRealm ne sont pas thread-safe et ne peuvent pas être partagés entre threads, vous devez donc get une instance RLMRealm dans chaque thread / dispatch_queue dans lequel vous voulez lire ou écrire.

Également à partir des documents Realm : RLMRealm objects RLMRealm sont mis en cache en interne par Realm, et l'appel de cette méthode plusieurs fois sur un seul thread au sein d'une seule itération de la boucle d'exécution renvoie normalement le même object RLMRealm .

Donc, sachant cela, j'ai modifié votre échantillon de code pour get le RLMRealm directement à partir du bloc dispatch_async où il est utilisé, sans encourir de pénalité de performance, car il est mis en cache.

J'ai également remarqué qu'un AccelerationEvent été passé à travers les threads, ce qui n'est pas autorisé. Cet exemple de code modifié passe donc NSSsortingng travers les threads.

 self.realmQueue = dispatch_queue_create("db", DISPATCH_QUEUE_SERIAL); self.motionManager = [[CMMotionManager alloc] init]; self.motionManager.accelerometerUpdateInterval = 0.001; __block int i = 0; __block BOOL shouldBeginWriteTransaction = YES; [self.motionManager startAccelerometerUpdatesToQueue:[[NSOperationQueue alloc] init] withHandler:^(CMAccelerometerData *accelerometerData, NSError *error) { dispatch_async(self.realmQueue, ^{ RLMRealm *realm = [RLMRealm realmWithPath:[NSTemporaryDirectory() ssortingngByAppendingPathComponent:@"temp"]]; if (shouldBeginWriteTransaction) { [realm beginWriteTransaction]; shouldBeginWriteTransaction = NO; } AccelerationEvent *event = [[AccelerationEvent alloc] init]; event.x = accelerometerData.acceleration.x; event.y = accelerometerData.acceleration.x; event.z = accelerometerData.acceleration.y; event.time = [NSDate date]; [realm addObject:event]; if (i % 1000) { NSSsortingng *xSsortingng = [NSSsortingng ssortingngWithFormat:@"%f", event.x]; NSSsortingng *ySsortingng = [NSSsortingng ssortingngWithFormat:@"%f", event.y]; NSSsortingng *zSsortingng = [NSSsortingng ssortingngWithFormat:@"%f", event.z]; dispatch_async(dispatch_get_main_queue(), ^{ self.xLabel.text = xSsortingng; self.yLabel.text = ySsortingng; self.zLabel.text = zSsortingng; }); } if (i % 10000 == 0) { NSDate *startDate = [NSDate date]; [realm commitWriteTransaction]; NSLog(@"save time: %f", [[NSDate date] timeIntervalSinceDate:startDate]); shouldBeginWriteTransaction = YES; } i++; }); }]; 

Je n'ai pas exécuté ce code pour confirmer que cela fonctionne, alors laissez-moi savoir si cela ne résout toujours pas le problème.