From Realm docs: RLMRealm
objects are not thread safe and cannot be shared across threads, so you must get an RLMRealm
instance in each thread/dispatch_queue in which you want to read or write.
Also from Realm docs: RLMRealm
objects are cached internally by Realm, and calling this method multiple times on a single thread within a single iteration of the run loop will normally return the same RLMRealm
object.
So knowing this, I modified your code sample to get the RLMRealm
directly from the dispatch_async
block where it is used, without incurring a performance penalty, since it is cached.
I also noticed that an AccelerationEvent
was passed across threads, which is also not allowed. So this modified code sample passes NSString
s across threads instead.
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++;
});
}];
I haven't run this code to confirm that it works, so let me know if this still doesn't resolve the issue.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…