Realm accessed from incorrect thread

后端 未结 1 435
再見小時候
再見小時候 2020-12-06 16:38

I\'m using serial GCD queue to work with realm. Application crashes with Realm accessed from incorrect thread exception when GCD starts to switch threads for th

相关标签:
1条回答
  • 2020-12-06 17:26

    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 NSStrings 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.

    0 讨论(0)
提交回复
热议问题