3
votes

I'm using Realm for a messaging app. I need to modify some of the queried objects, for example if the object is a media message that does not yet have a thumbnail. I then download it and attempt to save it to the object.

I could have multiple downloads running at the same time as this is taken place inside a for loop. Why would it throw this exception if I am allocating a new instance of my default Realm for every object save?

I tried wrapping the download block in a dispatch_async, thinking it could be a race condition or something related but had no luck, still throws the exception.

'RLMException', reason: 'Realm accessed from incorrect thread'

RLMResults *messages = [[Message objectsWhere:@"jabberID = %@", self.recipientJID] sortedResultsUsingProperty:@"date" ascending:YES];

for (Message *message in messages) {
  if (!message.hasThumbData) {

    [self downloadMedia:message.remoteMediaURL success:^(NSData *mediaData) {

      RLMRealm *realm = [RLMRealm defaultRealm];
      [realm beginWriteTransaction];
      message.hasThumbData = YES;
      message.thumbData = mediaData;
      [realm commitWriteTransaction]; 

    } failure:^(NSError *error) {
      NSLog(@"Error downloading media: %@", error.description);
    }];

  }
} 
1

1 Answers

2
votes

Persisted Realm objects can only be read from or written to on the same thread as they were fetched on. Assuming that the success block for [self downloadMedia:success:failure:] is being called on a different thread than messages was read on, this means that you can't use message within the block. Creating a new RLMRealm instance for the current thread does not have any effect on the captured variables.