Reputation: 2312
I have a number of attributes for a CorData entity that are based on the values of other attributes. For example transactionTotalValue = transactionPrice * transactionQuantity. Currently I subclassed the NSManagedObject and created custom setters like this
- (void)setTransactionQuantity:(NSDecimalNumber *)transactionQuantity
{
[self willChangeValueForKey:@"transactionQuantity"];
[self setPrimitiveValue:transactionQuantity forKey:@"transactionQuantity"];
[self didChangeValueForKey:@"transactionQuantity"];
[self updateTotalValue];
}
- (void)setTransactionPrice:(NSDecimalNumber *)transactionPrice
{
[self willChangeValueForKey:@"transactionPrice"];
[self setPrimitiveValue:transactionPrice forKey:@"transactionPrice"];
[self didChangeValueForKey:@"transactionPrice"];
[self updateTotalValue];
}
- (void)updateTotalValue
{
self.transactionTotalValue = [self.transactionQuantity decimalNumberByMultiplyingBy:[NSDecimalNumber decimalNumberWithDecimal:[self.transactionPrice decimalValue]]];
}
Is this an acceptable way of doing this? if not what would be considered best practice for this situation?
The other alternative is to use KVO as follows
- (NSDecimalNumber *)transactionTotalValue
{
[self willAccessValueForKey:@"transactionTotalValue"];
NSDecimalNumber *total = [self.transactionQuantity decimalNumberByMultiplyingBy:[NSDecimalNumber decimalNumberWithDecimal:[self.transactionPrice decimalValue]]];
[self didChangeValueForKey:@"transactionTotalValue"];
return total;
}
+ (NSSet *)keyPathsForValuesAffectingValueForKey:(NSString *)key
{
NSSet *keypaths = [super keyPathsForValuesAffectingValueForKey:key];
if ([key isEqualToString:@"transactionTotalValue"]) {
NSArray *affectingKeys = @[@"transactionQuantity", @"transactionPrice"];
keypaths = [keypaths setByAddingObjectsFromArray:affectingKeys];
}
return keypaths;
}
Is this the better option?
Upvotes: 2
Views: 200
Reputation: 195
The attribute transactionTotalValue
is to be completely dependent upon the two other attributes.
Declare it as a readonly, nonatomic property.
@property (nonatomic,readonly) id transactionTotalValue;
You can then implement the getter.
- (id)transactionTotalValue
{
//check for non-existent needed properties and handle here
return [self.transactionQuantity
decimalNumberByMultiplyingBy:[NSDecimalNumber
decimalNumberWithDecimal:[self.transactionPrice decimalValue]]];
}
Also override the class method for keys that affect the dependent property.
+ (NSSet *)keyPathsForValuesAffectingTransactionTotalValue
{
return [NSSet setWithObjects:@"transactionQuantity", @"transactionPrice", nil];
}
The transactionTotalValue
property will be re-read as needed, say if you are updating a table source through bindings. By making it readonly you will be able to avoid any setter methods.
Upvotes: 1