Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

With CoreData, if I have an @dynamic property, can I override its getter just like it was @synthesized? (Lazy Instantiation)

Using CoreData I created an entity, then I subclassed it into its own file, where it has the @propertys, then it has the @dynamic parts in the .m file.

When I want something to have a certain value if it's never been set, I always use lazy instantiation, like follows:

- (NSString *)preview {
    if ([self.body length] < 200) {
        _preview = self.body;
    }
    else {
        _preview = [self.body substringWithRange:NSMakeRange(0, 200)];
    }

    return _preview;
}

But how do I do this with @dynamic properties? If I do the same thing, it says _preview is an undeclared property, but it's in the .h file. What do I do different to lazy instantiate it?

like image 941
user212541 Avatar asked Apr 06 '13 17:04

user212541


2 Answers

One standard method is to define preview as a transient attribute in the Core Data model (so that the value is not actually stored in the database), and implement a custom getter method. In your case it would look like:

- (NSString *)preview
{
    [self willAccessValueForKey:@"preview"];
    NSString *preview = [self primitiveValueForKey:@"preview"];
    [self didAccessValueForKey:@"preview"];
    if (preview == nil) {
        if ([self.body length] < 200) {
            preview = self.body;
        } else {
            preview = [self.body substringWithRange:NSMakeRange(0, 200)];
        }
        [self setPrimitiveValue:preview forKey:@"preview"];
    }
    return preview;
}

(You can provide custom getter, setter methods for @dynamic properties. However, Core Data properties are not simply backed up by instance variables. That is the reason why you cannot access _preview.)

If you need the preview to be re-calculated if the body attribute changes, then you must also implement a custom setter method for body that sets preview back to nil.

For more information, read Non-Standard Persistent Attributes in the "Core Data Programming Guide".

Update: The current version of the Core Data Programming Guide does not contain that chapter anymore. You can find an archived version from the Way Back Machine. Of course this has to be taken with a grain of salt since it is not part of the official documentation anymore.

like image 54
Martin R Avatar answered Sep 27 '22 18:09

Martin R


See documentation on using primitiveValueForKey:

basically:

@dynamic name;

- (NSString *)name
{
    [self willAccessValueForKey:@"name"];
    NSString *myName = [self primitiveName];
    [self didAccessValueForKey:@"name"];
    return myName;
}

- (void)setName:(NSString *)newName
{
    [self willChangeValueForKey:@"name"];
    [self setPrimitiveName:newName];
    [self didChangeValueForKey:@"name"];
}
like image 25
Dan Shelly Avatar answered Sep 27 '22 18:09

Dan Shelly