领域访问不正确的线程

我正在使用串行GCD队列来处理领域。 当GCD开始切换队列的Realm accessed from incorrect thread时,应用程序崩溃与Realm accessed from incorrect threadexceptionRealm accessed from incorrect thread的区域。 有什么方法可以将给定的领域与使用GCD API的线程绑定?

这是一个简单的例子

 self.realmQueue = dispatch_queue_create("db", DISPATCH_QUEUE_SERIAL); __block RLMRealm *realm = nil; dispatch_async(self.realmQueue, ^{ realm = [RLMRealm realmWithPath:[NSTemporaryDirectory() stringByAppendingPathComponent:@"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 = [NSString stringWithFormat:@"%f", event.x]; self.yLabel.text = [NSString stringWithFormat:@"%f", event.y]; self.zLabel.text = [NSString stringWithFormat:@"%f", event.z]; }); } if (i % 10000 == 0) { NSDate *startDate = [NSDate date]; [realm commitWriteTransaction]; NSLog(@"save time: %f", [[NSDate date] timeIntervalSinceDate:startDate]); shouldBeginWriteTransaction = YES; } i++; }); }]; 

从领域文档 : RLMRealm对象不是线程安全的,不能跨线程共享,因此您必须在每个要读取或写入的线程/ dispatch_queue中获取RLMRealm实例。

同样来自Realm文档 : RLMRealm对象由Realm在内部caching,并且在运行循环的单个迭代内的单个线程上多次调用此方法将通常返回相同的RLMRealm对象。

所以知道这一点,我修改了你的代码示例,直接从dispatch_async块中获取RLMRealm ,而不会因为caching而导致性能损失。

我也注意到AccelerationEvent是通过线程传递的,这也是不允许的。 所以这个修改过的代码示例代之以跨线程传递NSString

 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() stringByAppendingPathComponent:@"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) { NSString *xString = [NSString stringWithFormat:@"%f", event.x]; NSString *yString = [NSString stringWithFormat:@"%f", event.y]; NSString *zString = [NSString stringWithFormat:@"%f", event.z]; dispatch_async(dispatch_get_main_queue(), ^{ self.xLabel.text = xString; self.yLabel.text = yString; self.zLabel.text = zString; }); } if (i % 10000 == 0) { NSDate *startDate = [NSDate date]; [realm commitWriteTransaction]; NSLog(@"save time: %f", [[NSDate date] timeIntervalSinceDate:startDate]); shouldBeginWriteTransaction = YES; } i++; }); }]; 

我没有运行这个代码来确认它的工作,所以让我知道这是否仍然不能解决问题。