small medium large xlarge

Back to: All Forums  Core Data
Generic-user-small
15 Apr 2011, 13:49
Greg Robertson (21 posts)

If I have an object with 3 properties, lets say Box and it has attributes of height, width and area. I would like to create an automatic setter that would be called whenever height or width was set that would set the area but the accessors would just be the dynamic ones built automatically.

I am looking for what the best practice would be to set ‘area’ automatically whenever width or height are set. I can’t find a good example online on how to do this. If I write a custom accessor then it won’t work on a query of the persistent store, so I need to use a setter to push the data into the persistent store.

Also I did not see a good example of this in the book but maybe I missed it, if there is an example in the box can you let me know which page so I can read more.

Does the below look correct?

Thanks

Greg

#import <Foundation/Foundation.h>
#import <CoreData/CoreData.h>

@interface Box: NSManagedObject
{
@private
}
@property (nonatomic, retain) NSNumber * height;
@property (nonatomic, retain) NSNumber * width;
@property (nonatomic, retain) NSNumber * area;

@end

</code>

#import "Box.h"


@implementation Box

@dynamic height;
@dynamic width;
@dynamic area;


- (void)setHeight:(NSNumber *)value
{
    [self willChangeValueForKey:@"height"];
    [self setPrimitiveValue:value forKey:@"height"];     
    [self didChangeValueForKey:@"height"];
     
     double heightDouble = [value doubleValue];
     double widthDouble = [width doubleValue];
     double areaDouble = heightDouble * widthDouble;
    NSNumber *areaNumber = [NSNumber numberWithDouble: areaDouble];
     
     [self willChangeValueForKey:@"area"];
     [self setPrimitiveValue: areaNumber forKey:@"area"];
     [self didChangeValueForKey:@"area"];
}

- (void)setWidth:(NSNumber *)value
{
    [self willChangeValueForKey:@"width"];
    [self setPrimitiveValue:value forKey:@"width"];     
    [self didChangeValueForKey:@"width"];
     
     double widthDouble = [value doubleValue];
     double heightDouble = [height doubleValue];
     double areaDouble = heightDouble * widthDouble;
    NSNumber *areaNumber = [NSNumber numberWithDouble: areaDouble];
     
     [self willChangeValueForKey:@"area"];
     [self setPrimitiveValue: areaNumber forKey:@"area"];
     [self didChangeValueForKey:@"area"];
}

</code>

Avatarsmall_pragsmall
11 Dec 2011, 20:25
Marcus S. Zarra (284 posts)

There are a couple of ways to do this. Personally I would set up a KVO (Key Value Observer) on the height and width. That way whenever either is changed your object will get called and given the chance to recalculate area.

You can set up the KVO in @-awakeFromInsert@ and @-awakeFromFetch@. Then you would want to tear down the KVO in the @-willTurnIntoFault@.

You must be logged in to comment