johnnyb
johnnyb

Reputation: 712

Key-Value Type Coercion in iOS

I am writing an application using Core Data which heavily depends on setting attributes from string values. However, I am running into a problem because Core Data, when it creates wrapper methods, uses NSNumber to represent all of the numeric fields. Therefore, if I pass in a String using key/value coding setValue:forKey: it gives me a type error:

For instance, I have an object type "Building". In the datamodel, I have an attribute called "fbFloors" set to integer 32.

Then, in my code, I do the following:

Building * b = [NSEntityDescription insertNewObjectForEntityForName:@"Building" inManagedObjectContext:ctx]; [b setValue:@"2" forKey:@"fbFloors"];

This raises the following exception:

Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Unacceptable type of value for attribute: property = "fbFloors"; desired type = NSNumber; given type = __NSCFConstantString; value = 2.'

I would like it to coerce the string value to a number, but it doesn't want to. I tried implementing coerceValueForFbFloors: but it looks like that is only available in Mac OS X, not iOS.

Any ideas?

Upvotes: 2

Views: 1363

Answers (2)

Jody Hagins
Jody Hagins

Reputation: 28339

What if you did something like this...

- (NSNumber*)fbFloorsValue:(NSString*)valueString
{
    return [NSNumber numberWithInteger: [valueString integerValue]];
}

where you have a method for each non-string attribute. Then when you set those values in a generic way...

Assume your key ("fbFloors") is in a variable called and your value ("2") is in a variable called ...

id valueObject;
SEL selector = NSSelectorFromString([NSString stringWithFormat:@"%@Value:", key]);
if (selector && [self respondsToSelector:selector]) {
    valueObject = [self performSelector:selector withObject:value];
} else {
    valueObject = value;
}
Building * b = [NSEntityDescription insertNewObjectForEntityForName:@"Building" inManagedObjectContext:ctx]; [b setValue:valueObject forKey:@key];

Upvotes: 1

Denis Hennessy
Denis Hennessy

Reputation: 7463

You have to pass an actual instance of NSNumber to setValue. Something like:

[b setValue[NSNumber numberWithInt:2] forKey:@"fbFloors"];

If your data is appearing as a string, then you can use NSNumberFormatter to convert it first to an NSNumber.

Upvotes: 0

Related Questions