I have a CoreData model which has a non-standard attribute as a member. So I have a subclass of NSValueTransformer to convert the object to NSData and back. This member has 2 properties of type NSNumber... max and min. I implement them with standard property declarations and let the compiler synthesize their accessors, so I assume everything is KVC compliant.
If I try to bind max or min to a NSTextCell (yes, there is a number formatter on the NSTextCell), I can edit those values, thinking something happened, but when I save my managedObjectContext, and restart the app, only the init values of those objects are showing.
In the CoreData model for that attribute (call it timeRange), I set his value transformer to something correct, but it seems that the binding is working in one direction only. I can't seem to edit these values have have them make their way back to the model.
By contrast, the object that has the timeRange attribute also has a simple number attribute (as I wanted to be sure I got the mechanism for modifying number attributes working), and these changes are propagated to the persistent store.
The question is, what am I doing wrong? what might my implementation be missing? I presume that once you specify a value transformer on your non-standard attribute (in the Core Data model editor for that attribute), you then work with that attribute everywhere else as if it is as it's suppose to be, in this case SCTimeRange, not NSData.
So, if this is true, and my model has an attribute of type SCTimeRange, why can't I set its very simple NSNumber properties? Does it have something to do with the Number Formatter on the NSTextCell not being bound to anything else? i.e. the column doesn't know about that?
@interface SCTimeRange : NSObject <NSCoding>
@property (nonatomic, strong) NSNumber *max;
@property (nonatomic, strong) NSNumber *min;
@end
@implementation SCTimeRange
- (id)init
{
self = [super init];
if (self) {
self.max = @(0.0f);
self.min = @(0.0f);
}
return self;
}
- (id)initWithCoder:(NSCoder *)aDecoder
{
self = [super init];
if (self) {
self.max = [aDecoder decodeObjectForKey:@"max"];
self.min = [aDecoder decodeObjectForKey:@"min"];
}
return self;
}
- (void)encodeWithCoder:(NSCoder *)aCoder
[aCoder encodeObject: self.max forKey:@"max"];
[aCoder encodeObject: self.min forKey:@"min"];
}
@end
And the Value Transformer:
@implementation SCTimeRangeTransformer
+(Class)transformedValueClass {
return [NSData class];
}
+ (BOOL)allowsReverseTransformation { return YES; }
-(id)transformedValue:(id)value {
if (value == nil) {
return nil;
} else if ([value isKindOfClass:[NSData class]]){
NSData *data = (NSData*)value;
return data;
}
else if ([value isKindOfClass:[SCTimeRange class]])
{
NSData *data = [NSKeyedArchiver archivedDataWithRootObject: (SCTimeRange*)value];
return data;
}
return nil;
}
- (id)reverseTransformedValue:(id)value
{
if (value == nil) {
return nil;
}
else if ([value isKindOfClass:[SCTimeRange class]])
{
return value;
}
else if ([value isKindOfClass:[NSData class]]){
NSData *data = (NSData*)value;
SCTimeRange *range = (SCTimeRange*)[NSKeyedUnarchiver unarchiveObjectWithData: data];
return range;
}
return nil;
}
@end