Objective-C setValue:forKey on c primitive types

koalamo picture koalamo · Aug 3, 2013 · Viewed 7.4k times · Source

I'm trying to teach myself objective-c using the big nerd ranch book, it is a really great book but certain aspects confuse me.

The current chapter is talking about using setValue:forKey function which I understand is a method defined in NSObject. The book says that you can use this on a c primitive like int or float and gives this example

I have a custom class called Appliance and in it is an integer instance variable called voltage that stores the voltage of the current appliance I initialize a new appliance called a

appliance *a = [[appliance alloc]init];
[a setValue:[NSNumber numberWithInt:240] forKey:@"voltage"];

he then sets up a custom setter for voltage and logs the voltage when its called to prove it works

-(void)setVoltage:int(x) {
NSLog(@"setting voltage to %d",x);
voltage =x;
}

whats confusing me is that NSNumber numberWithInt returns a pointer to an NSNumber object thats stored on the heap correct? so then how does he log the integer stored in NSNumber using the %d token. I understand that would log an integer but isn't an object being passed in? furthermore I thought that since voltage was defined as an integer and not a pointer to something it couldn't hold the address to an object in its memory? or is NSNumber kind of forcing it to hold its memory address without actually having voltage being declared as a pointer?

sorry for the confusion this chapter basically kicked my butt.

Answer

Martin R picture Martin R · Aug 3, 2013

The conversion between objects and scalar types is handled automatically by the Key-Value Coding methods. From the documentation:

The default implementations of valueForKey: and setValue:forKey: provide support for automatic object wrapping of the non-object data types, both scalars and structs.

Once valueForKey: has determined the specific accessor method or instance variable that is used to supply the value for the specified key, it examines the return type or the data type. If the value to be returned is not an object, an NSNumber or NSValue object is created for that value and returned in its place.

Similarly, setValue:forKey: determines the data type required by the appropriate accessor or instance variable for the specified key. If the data type is not an object, then the value is extracted from the passed object using the appropriate -<type>Value method.

So in your case, intValue is applied automatically to the passed NSNumber object, and the resulting integer is passed to setVoltage:.