sahara108
sahara108

Reputation: 2859

RLMObject unable to use as a normal object

I have a Product model with the header:

@interface Product : RLMObject <NSCopying,NSCoding>
{
}
@property (nonatomic, strong) NSString *title;
@property (nonatomic, strong) NSString *thumbnailURL;
@property (nonatomic, strong) UIImage *thumbnail;

-(id)initWithInfo:(NSDictionary*)dictionary;
-(UIImage*)getThumbnail;

and implementation:

@implementation Product

-(id)initWithInfo:(NSDictionary*)dictionary
{
    self = [self init];
    if (self) {
        _title = dictionary[@"title"];
        _thumbnailURL = dictionary[@"thumbnailURL"];
        _thumbnail = [self getThumbnail];
    }

    return self;
}

-(UIImage*)getThumbnail
{
    if (_thumbnail) {
        return _thumbnail;
    }

    //load image from cache
    return [self loadImageFromCache];
}

Now, when I try to create a Product object and insert it into Realm, I always get the exception

[RLMStandalone_Product getThumbnail]: unrecognized selector sent to instance 0xcd848f0'

Now, I remove _thumbnail = [self getThumbnail]; and it works fine. But then I get another exception

[RLMStandalone_Product title]: unrecognized selector sent to instance 0xd06d5f0'

when I reload my view. I have created my Product object in the main thread, so it should be fine to using its property and method, isn't it?

Any advice will be appreciated!

Upvotes: 1

Views: 2115

Answers (1)

jpsim
jpsim

Reputation: 14409

Because Realm object properties are backed by the database rather than in-memory ivars, accessing those properties' ivars is not supported. We're currently clarifying our docs to convey this:

Please note that you can only use an object on the thread from which is was created or obtained, ivars shouldn't be accessed directly for any persisted properties, and that getters and setters for persisted properties cannot be overridden.

So to work with Realm, your model should look like this:

@interface Product : RLMObject

@property NSString *title;
@property NSString *thumbnailURL;
@property (nonatomic, strong) UIImage *thumbnail;

@end

@implementation Product

-(UIImage*)thumbnail
{
    if (!_thumbnail) {
        _thumbnail = [self loadImageFromCache];
    }
    return _thumbnail;
}

-(UIImage*)loadImageFromCache
{
    // Load image from cache
    return nil;
}

+(NSArray*)ignoredProperties
{
    // Must ignore thumbnail because Realm can't persist UIImage properties
    return @[@"thumbnail"];
}

@end

And usage of this model could look like this:

[[RLMRealm defaultRealm] transactionWithBlock:^{
    // createInDefaultRealmWithObject: will populate object keypaths from NSDictionary keys and values
    // i.e. title and thumbnailURL
    [Product createInDefaultRealmWithObject:@{@"title": @"a", @"thumbnailURL": @"http://example.com/image.jpg"}];
}];

NSLog(@"first product's image: %@", [(Product *)[[Product allObjects] firstObject] thumbnail]);

Notice how initWithInfo isn't necessary because RLMObject already has initWithObject: and createInDefaultRealmWithObject: already do this.

Upvotes: 3

Related Questions