What am I missing about using a newly committed object?


#1

I have an RLMObject with an RLMArray property.

In a new document I initialize the object, add some other objects to the array, and then commit it to the datastore.

However, when I later try and query the array I get a message:

This method may only be called on RLMArray instances from an RLMRealm

Do I need to re-acquire the object? Or is there some way to “refresh” it?

Thanks.

Matt


#2

Please share a code snippet that demonstrates how you’re creating and adding the object to the Realm.


#3

Been away sick, coming back to this now. The original error I was getting I solved by tinkering (i.e. I can’t remember how), but I have it again now.

The problem is with a call to:

- (ThingAttribute *)attribute:(NSString *)name {
  return [[self.attributes objectsWhere:@"name=%@",name] firstObject];
}

where ‘attributes’ is an RLMArray.

The context in which this call is made is an ‘-init’ method call on my RLMObject sub-class which is setting up default values for the object, including some ThingAttributes.

The code doing this is testing whether there is already an attribute with the given name to determine whether to add one or amend the existing one.


#4

There are three methods that will raise the exception you describe when called on unmanaged arrays: -objectsWithPredicate:, -sortedResultsUsingDescriptors:, and -addNotificationBlock:. Some of these methods may have other variants that funnel down to them (i.e., -objectsWhere: eventually calls -objectsWithPredicate:), and will also result in the same exception.


#5

Apologies, I’ve been editing and re-editing my message as I’ve dug into the problem. I missed you had already replied.

But, as you rightly identify objectsWhere: is the problem. Thanks.

Here’s my problem in a nutshell:

I need to initialise the contents of the RLMArray and I have methods, e.g. for integers:

- (void)setAttribute:(NSString *)name integer:(NSInteger)value {
  ThingAttribute *attr = [self attribute:name];
  if( attr ) {
    if( [attr kind] != ATTR_INTEGER ) {
      [self.attributes removeObjectAtIndex:[self.attributes indexOfObject:attr]];
      ThingAttribute *newAttr = [[ThingAttribute alloc] initWithName:name integer:value];
      [self.attributes addObject:newAttr];
    } else {
      [attr setIntegerValue:value];
    }
  } else {
    ThingAttribute *newAttr = [[ThingAttribute alloc] initWithName:name integer:value];
    [self.attributes addObject:newAttr];
  }
}

Now it seems like I need to guard all of these methods (and, sadly, there are 22 of them) with code to see if the object is not managed yet and avoid the lookup on the RLMArray?

Why did you decide that throwing an exception in this situation was the right thing to do, I’m curious?


#6

Okay, a little grisly (as indeed is having 22 of these damn methods!) but ultimately a simple edit to check [self realm] and just insert a new ThingAttribute instead of checking if one exists.