Become a MacRumors Supporter for $50/year with no ads, ability to filter front page stories, and private forums.

idelovski

macrumors regular
Original poster
Sep 11, 2008
235
0
UISwitch has property 'on' defined like this:

@property(nonatomic,getter=isOn) BOOL on;

So I always thought it means '-isOn' is getter and setter is just '-on', but now I discovered I can use '-on' as both setter and getter. So in this case we can have any of these expressions:

Code:
	BOOL       setting = theSwitch.isOn;
	BOOL       setting = theSwitch.on;
	BOOL       setting = [theSwitch isOn];

... but this fails to compile:
Code:
	BOOL       setting = [theSwitch on];

Anyone care to explain why second option works as getter and why last option doesn't.
 
Since you ask

I added this method to a test project

Code:
- (void)testSwitch
{
	UISwitch*	theSwitch = nil;
	BOOL       setting = theSwitch.isOn;
	BOOL       setting1 = theSwitch.on;
	BOOL       setting2 = [theSwitch isOn];
}
and I used the 'show assembly code' option for the file. This is most of the disassembled testSwitch code:

LM26:
movl -16(%ebp), %edx
leal L_OBJC_SELECTOR_REFERENCES_14-"L00000000002$pb"(%ebx), %eax
movl (%eax), %eax
movl %eax, 4(%esp)
movl %edx, (%esp)
call _objc_msgSend
movb %al, -11(%ebp)
LM27:
movl -16(%ebp), %edx
leal L_OBJC_SELECTOR_REFERENCES_14-"L00000000002$pb"(%ebx), %eax
movl (%eax), %eax
movl %eax, 4(%esp)
movl %edx, (%esp)
call _objc_msgSend
movb %al, -10(%ebp)
LM28:
movl -16(%ebp), %edx
leal L_OBJC_SELECTOR_REFERENCES_14-"L00000000002$pb"(%ebx), %eax
movl (%eax), %eax
movl %eax, 4(%esp)
movl %edx, (%esp)
call _objc_msgSend
movb %al, -9(%ebp)

This is compiled for the sim so it's x86 code. You can see that there are three, essentially identical, blocks of code that each maps to one of the lines in the source. Each block loads a selector into a register, does a couple more calculations, and then calls objc_msgSend and then saves the result. The selector that's loaded is called L_OBJC_SELECTOR_REFERENCES_14, which references this method name L_OBJC_METH_VAR_NAME_12, whose value is "isOn\0".

L_OBJC_METH_VAR_NAME_12:
.ascii "isOn\0"
.objc_message_refs
.align 2
L_OBJC_SELECTOR_REFERENCES_14:
.long L_OBJC_METH_VAR_NAME_12
.objc_meth_var_names

So what happens is that all three of those source lines call the method isOn. Obviously line 1 and line 3 are intended to call that method. But the compiler is translating theSwitch.on to [theSwitch isOn]. That works because you use the property syntax and the compiler knows that property names can vary according to certain rules.

This code:

Code:
BOOL       setting = [theSwitch on];

Is just a method call using the standard method call syntax. There are no rules for transforming method calls into something else. It doesn't know that you really want on to be isOn, so it fails.

Really, the odd thing is that on as getter is translated to isOn. I'm not sure if it's documented to do that.
 
On occasions like this I am truly sorry I never found time and need to learn assembly, but your guidance helped me understand all of the above.

Really, the odd thing is that on as getter is translated to isOn. I'm not sure if it's documented to do that.

I hope Michael Ash or Scott Stevenson would cover at least some of the oddities of Objective-C in their upcoming books.
 
As an Amazon Associate, MacRumors earns a commission from qualifying purchases made through links in this post.
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.