views:

1800

answers:

4

I'm calling valueForKey on an object. This returns an id which I tried to cast to a BOOL (because I know the value is a BOOL). But XCode gives the following warning:

"warning: cast from pointer to integer of different size..."

So what I ended up doing was this:

BOOL value = [[NSNumber numberWithInt:((NSInteger)[managedObject valueForKey:@"fieldName"])] boolValue];

I'm thinking that there must be an easier way. Is there?

A: 

well if it's a pointer, then you need to dereference before casting

Dasuraga
This comment is totally unrelated to the question that was asked.
Peter Parker
+11  A: 

-valueForKey: always returns an object. id is the objective-c type for pointer to any object.

You can examine the object in the debugger. Some useful commands:

po value
po [value class]

You'll find that the value is actually an NSNumber, so you can send it the -boolValue message to get the BOOL flag you are interested in.

Jim Correia
A: 

I'm skeptical of this in the first place because you shouldn't be placing a BOOL into any collection or object you can call valueForKey: on. Generally, collections that observe key-value coding should only contain objects as values (hence the id type of values to be inserted).

This is especially true of Core Data objects, which I think you're using - they don't allow people to store BOOLs as BOOLs, but instead as NSNumbers (technically NSCFBoolean, a private subclass of NSNumber).

What you should probably do is, where you insert the value (if Core Data doesn't do it for you), wrap the BOOL in an NSNumber. Something like:

// Given some NSManagedObject *managedObject with Boolean property boolProperty
BOOL myBool = YES;
NSNumber *myBoolAsNumber = [NSNumber numberWithBool:myBool];
managedObject.boolProperty = myBoolAsNumber;

Then, when you fetch it, you can grab the BOOL value back out again using NSNumber's boolValue method. For example:

// Given same managedObject:
NSNumber *myBoolAsNumber = managedObject.boolProperty;
BOOL myBool = [myBoolAsNumber boolValue]
Tim
This isn't correct. You can call `valueForKey:` to get essentially any attribute of any object. For example, NSView's `hidden` property maps to `isHidden` and `setHidden:`, which return and take a bool, respectively.
Chuck
I totally understand what you're saying and yes, I am using managed objects. The reason I'm accessing the entity using valueForKey is because I have a method that performs some common operations on several different entities. At runtime, the method doesn't know the type of the entity that it will be operating on. Basically, I'm writing a method that needs to be generic to handle a specific operation across several different entities. All the entities that this method needs to operate on have a field with a specific name.
Peter Parker
Chuck: the `hidden` property maps to those two accessors, yes, but KVC boxes the BOOL inside an NSNumber on which you have to call `boolValue` before it's back to a BOOL. So while the accessor methods themselves take and return a BOOL, using KVC requires that you work with objects (hence the `id` return type).
Tim
+3  A: 

If the value of the key is a BOOL, then the returned object will be an NSNumber. You can just ask it for its boolValue. You can't simply cast from an object (id) to a BOOL or integer or any other non-object type. The KVC machinery autoboxes scalars into the appropriate value type, so you can just ask it for the type you want. You might be interested in the KVC docs — they explain this in more detail.

Chuck