1
votes

I’m porting an existing iOS app to Core Data (Xcode 5, Mavericks, iOS 7.1+). I need to import an existing sqlite3 database. I am auto-generating model files and then filling them with data from the database.

I have an auto-generated class that contains scalar types (I checked the Use Scalars box when auto-generating):

@interface Details : NSManagedObject

@property (nonatomic) float heightInches;
…

Auto-generation implements this property:

@implementation Details

@dynamic heightInches;
…

Then I try to set a value for this property using a float from the database:

Details* details = [NSEntityDescription insertNewObjectForEntityForName:@“Details” inManagedObjectContext:context];
[details setHeightInches:(float)sqlite3_column_double(statement, 10)];
…

When this line executes I get the following run-time error:

'NSInvalidArgumentException', reason: 'Unacceptable type of value for attribute: property = "heightInches"; desired type = NSNumber; given type = NSManagedObject; value = (entity: Details; id: 0x1002286a0 ; data: { heightInches = 0; …

I get the same run-time error if I redefine the implementation:

@synthesize heightInches;

And I get a compile-time error (type mismatch) if I try to pass in a NSNumber instead of a float:

[details setHeightInches:[NSNumber numberWithFloat:(float)sqlite3_column_double(statement, 10)]];

Why does Core Data expect an NSNumber when the data type is float? Why does Core Data see the float I’m passing in as NSManagedObject? The int32_t values seem to be working. Is there something special I have to do for floats?

Thanks

1
Could you just abandon the scalar type and change to NSNumber?danh
Yes. I'll try that after I try writing my own getters and setters. I'm just resistant to giving up some Core Data advantages so early in the game.David U
Gotcha. But I think the core data advantage is in allowing you to represent objects instead of numbers. One advantage of NSNumber is you get nil (vs. 0.00) as a distinct state.danh
Simple getters and setters produced the same run-time error. Using NSNumber works. This is scientific data. Null values don't occur. I'd rather not have to type integerValue and floatValue endlessly :(David U
I wonder if it's tripping up on formatting of the scalars in the source data. Anyway, I think NSNumbers is a good choice. Sorry I don't have an answer to your real question. (I'm a core data dilettante).danh

1 Answers

1
votes

I'm going to take a somewhat contrarian approach and argue that it doesn't matter because you are making a bad design decision even attempting to do things this way.

You mention in a comment that this is scientific data. But you're assigning it to a float, which invites lack of precision due to the usual problems of representing decimal values in a floating point variable.

What you should do instead is declare the attribute in the data model as Decimal. When you generate subclasses that will be represented as an NSDecimalNumber (there is no scalar equivalent, so checking that box won't make any difference). NSDecimalNumber is certainly not perfect, but in cases where you have decimal values and really care about precision (e.g.: science, finance) it's the right choice.

As for what's actually going wrong in this case, I'm not completely certain. Using setHeightInches should work exactly as you'd expect it to work. Your error message suggests that there's more going on than the details in your question suggest, because it's not complaining about wanting an NSNumber instead of a float. It's complaining that it received an NSManagedObject as the value, but the code snippet doesn't show that. It doesn't matter though, because float is still the wrong choice in this situation.