First, some context: while answering questions on SO, I came across a post wherein the author had been trying to set a getter with syntax similar to [self.propertyGetter:newValue];. For some reason, this compiles, and I thought to myself, “this would constitute a call to nil, wouldn’t it?”. So, my question is, why in the heck does this ‘work’? (to be perfectly clear, the poster was complaining that this had no effect, so by ‘work’, I mean compile).
First, some context: while answering questions on SO, I came across a post wherein
Share
The code you quoted is
[self.propertyGetter:newValue]. Here’s how the Objective-C compiler parses this.The first thing after the left bracket has to be the receiver of the message. In that code, the receiver is the value of
self.propertyGetter. The compiler transformsself.propertyGetterinto[self propertyGetter]. So we can rewrite the code you quoted as[[self propertyGetter]:newValue].Now the compiler needs to figure out the selector of the message. You usually see a keyword selector like
setStatusBarHidden:animated:, which is a series of keywords followed by colons. But it turns out a keyword can be zero-length. So a colon by itself is a valid keyword selector. So the compiler sees it like this:[[self propertyGetter] :newValue]. (Using a zero-length keyword is almost always very bad style.)You can declare an instance method using that selector. For example:
If
[self propertyGetter]returns an object of a class that has that method, the code will compile and run.If the compiler has seen any class with a method named like that, and
[self propertyGetter]returns typeid, then the code will compile (becauseidis a wildcard type and the compiler will not complain if you try to send it any known message selector). However, the app will crash at runtime if[self propertyGetter]doesn’t actually understand the:message.