3

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);
    }];

  }
} 
Marcos Curvello
  • 873
  • 13
  • 25

1 Answers1

2

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.

Thomas Goyne
  • 8,010
  • 32
  • 30
  • The success block is being called on the main thread, and so is the RLMResults. – Marcos Curvello May 16 '15 at 00:32
  • @MarcosCurvello did you find any solution? I have same situation. – Nik May 17 '15 at 14:20
  • No I did not find a solution for this. I find it funny because I know all actions are performed on the main thread. Any suggestions here [@Thomas Goyne](http://stackoverflow.com/users/2340687/thomas-goyne)? – Marcos Curvello May 18 '15 at 13:26
  • Is it possible you're nilling out the block on a background thread? – segiddins May 18 '15 at 14:58
  • @segiddins No, that's a possibility, I'm using the same download block when the user taps on a media that already has thumbnail to download the full res, and in this case I am able to resave my RLMObject. – Marcos Curvello May 18 '15 at 16:14
  • In that case, can you share a backtrace when the exception is being thrown? – segiddins May 18 '15 at 18:29
  • @segiddins I think this issue lies in `AFNetworking`. I'm using an instance of `AFHTTPRequestOperationManager`. I tried the same operation with a plain `NSURLConnection sendAsynchronousRequest` and successfully downloaded all objects. Here's the [stack-trace](https://gist.github.com/marcoscurvello/cd7c637e0f5bfeb3ade3). – Marcos Curvello May 18 '15 at 20:39
  • Yup, the issue here is definitely the block being `nil`ed out on a different thread, which is releasing the objects it closes over. – segiddins May 19 '15 at 21:57