Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Objective-C: override dynamic getter

I have an NSManagedObject subclass MyClass with a property myProp, which is defined @dynamic. There are various instances of reading myProp in my code, via [myClass myProp].

Now, I want to define a getter (that returns myProp after appending something to it) for myProp, without changing the various calls to [myClass myProp]. i.e. without creating a getter that is named something other than getMyProp.

My question is, if I create a getter getMyProp, which will override the getter created by NSManagedObject, how do I access the original value that is stored in the database?

like image 669
Akshay Avatar asked Sep 13 '11 14:09

Akshay


1 Answers

To access the underlying values of a managed object you use the following two methods:

- (id)primitiveValueForKey:(NSString *)key

- (void)setPrimitiveValue:(id)value forKey:(NSString *)key

This is often used to convert NSNumber attributes into their 'real' type, for example a bool property:

- (BOOL)isShared
{
    [self willAccessValueForKey:@"isShared"];
    NSNumber *underlyingValue = [self primitiveValueForKey:@"isShared"];
    [self didAccessValueForKey:@"isShared"];
    return [underlyingValue boolValue];
}

The willAccessValueForKey: and didAccessValueForKey: are required by the underlying managed object class for handling faults and relationships etc.

And if you do end up writing a setter, you must also wrap the accessor in KVC methods:

- (void)setShared:(BOOL)isShared
{
    NSNumber *newUnderlyingValue = [NSNumber numberWithBool:isShared];
    [self willChangeValueForKey:@"isShared"];
    [self setPrimitiveValue:newUnderlyingValue forKey:@"isShared"];
    [self didChangeValueForKey:@"isShared"];
}

Having said this, I would personally not recommend you keep the same method name unless you have a good reason. For 'derived' values you generally want to create a brand new method with a different name. It doesn't take long to do a quick find/replace throughout your code.

EDIT: added willAccessValueForKey:/didAccessValueForKey: (thanks jrturton)

like image 149
Mike Weller Avatar answered Oct 01 '22 16:10

Mike Weller