dot syntax vs method syntax with getter= - objective-c

I'm not sure how much use this question is but it seems interesting to me...
I thought that using property/synthesize statements was equivalent to me creating the getter/setter. Therefore
// .h
#property (nonatomic) BOOL on;
// .m
#synthesize on = _on;
// In my mind synthesizes the following methods
// - (BOOL)on;
// - (void)setOn:(BOOL)on;
However if I change the declarations to the following:
v
#property (nonatomic, getter=isOn) BOOL on;
#synthesize on = _on;
// In my mind synthesizes the following
// - (BOOL)isOn;
// - (void)setOn:(BOOL)on;
Then given the above I override the getter so I know when it is called:
- (BOOL)isOn;
{
NSLog(#"I was called");
return _on;
}
Now calling the following on an instance (myClass) results in:
NSLog(#"%d", [myClass isOn]);
//=> 2012-02-09 22:18:04.818 Untitled[1569:707] I was called
//=> 2012-02-09 22:18:04.820 Untitled[1569:707] 1
NSLog(#"%d", myClass.isOn);
//=> 2012-02-09 22:18:24.859 Untitled[1599:707] I was called
//=> 2012-02-09 22:18:24.861 Untitled[1599:707] 1
NSLog(#"%d", myClass.on); // This is the one I didn't expect to work
//=> 2012-02-09 22:18:55.568 Untitled[1629:707] I was called
//=> 2012-02-09 22:18:55.570 Untitled[1629:707] 1
I had always assumed that if I was using a property in this sense it was perfectly valid to use the getter/setter with dot syntax in the form
myClass.isOn;
myClass.on = on;
From another question it was suggested that when using dot syntax I should use the property name like this:
myClass.on // Correct
myClass.isOn // Incorrect
Although this works it seem slightly less logical because I know there is no underlying method - (BOOL)on it is instead mapped to - (BOOL)isOn
My questions are (using the latter example)
Is this a bug or should myClass.on really be silently changed to call - (BOOL)isOn
Semantically speaking I am accessing state not invoking behaviour so is my current use of dot syntax correct? (e.g. myClass.isOn)
Update
Although no one has explicitly said it I have reasoned that using .isOn is bad form because regardless of the fact that under the hood the same method is called, semantically isOn is asking a question, which is more behaviour rather than state.
However I am still unclear on where the "magic" wiring goes on that turns calls to myClass.on into [myClass isOn]
Update 2
After looking around the docs some more I found this section on Declared Properties. Using the following code I can inspect a class' properties:
id MyClass = objc_getClass("MyClass");
unsigned int outCount, i;
objc_property_t *properties = class_copyPropertyList(MyClass, &outCount);
for (i = 0; i < outCount; i++) {
objc_property_t property = properties[i];
NSLog(#"Name: %s, attributes: %s\n", property_getName(property), property_getAttributes(property));
}
//=> 2012-02-10 07:10:28.333 Untitled[934:707] Name: on, attributes: Tc,GisOn,V_on
So we have the following attributes:
name = on
type = char (Tc)
getter = isOn (GisOn)
variable = _on (V_on)
With all of this information available at runtime it kind of leaves the question is this lookup done at runtime or compile time like some answers suggest?

However I am still unclear on where the "magic" wiring goes on that turns calls to myClass.on into [myClass isOn]
The logic surely goes as follows, when compiling an obj.name in a getting context:
if(there is an accessible #property for name in scope)
{
if(there is a custom getter specified)
compile "[obj customGetter]"
else
compile "[obj name]"
}
else if (there is an an accessible instance method name in scope)
compile "[obj name]"
else
{
compile "[obj name]"
warn obj may not respond to name
}
There are other ways a language/execution environment can handle custom getter names, but given that Obj-C puts the declaration in the header (which is public) the above is a good guess as to where the custom getter logic is performed - when compiling the call site.

From your experiment we can infer that dot syntax is interpreted as follows:
is there a property with this name? If so, does it have a specified getter / setter name? if so, let's call that method.
otherwise, make up an appropriate method name (direct if we're getting, setXX if we're setting) and throw that at the receiver.
You can, for example, try to use .count against an NSArray instance. Before the abomination police kick in your doors, you may have time to see that it works.
To actually answer your question, in my mind dot notation should only be used to access properties, and in that case you should use the property name as declared in the interface. So .on for a UISwitch. I don't know why the getter name isn't given in the synthesize statement instead of the property declaration, it seems to belong in implementation rather than interface to me.

Well concerning dot notation, let me cite Aaron Hillegass (Cocoa Programming for Mac OSX, 3rd. Ed):
"Overall, I think that this is a rather silly addition to the language since we already had a syntax for sending messages."
When you have a member variable on, and your getter for this variable is called isOn then .on and .isOn are two very different kind of things. By using the getter (and probably a setter, too) you will adhere to the "information hiding" promise, whereas by using direct access to the member variables you won't. Cocoa won't enforce those things as it is relying on conventions. It's up to you to decide which way is right for you. Considering convention, you would have to stick to setters and getters - no matter what names you give them, though.

Property declarations are merely shorthand for regular method declarations. E.g.:
#property int color;
#property (getter=isOn) BOOL on;
becomes these method declarations:
- (int)color;
- (void)setColor:(int)value;
- (BOOL)isOn;
- (void)setOn:(BOOL)on;
You can call these methods just like any other method:
[foo color];
[foo isOn];
Likewise, dot notation is merely informal shorthand for calling plain old methods. For example:
x = #"Hello".length;
x = foo.on;
x = foo.isOn;
becomes
x = [#"Hello" length];
x = [foo isOn];
x = [foo isOn];
Note that #"Hello".length works even though NSString does not actually declare a property named "length". By default, foo.bar always expands to [foo bar] unless bar has been declared a property with a custom getter. If bar happens to be the name of a valid method then it will work without error.
Likewise, in your example foo.isOn works even though you don't actually declare a property named "isOn". Rather "isOn" is the name of a method that just happens to be the getter method for your "on" property.
So, while foo.isOn may work, it's considered bad form because isOn is not actually the name of the property.
What you cannot do is this:
x = [foo on]; // Error
because you never declare an on method.

Related

Show warnings or errors when redeclaring a variable

It seems that the default behavior in XCode is to silently allow redefinition of local variables if they are declared in a deeper scope, but throw an error or warning otherwise. For example, XCode produces an error for "Redefinition of 'var'" if it is redefined in the exact same scope:
- (void) doStuff
{
NSString *var = #"Hello World";
NSString *var = #"Goodbye"; // Error on this line
}
Similarly, if I have an ivar called 'var', and I try to re-declare 'var' in a local method, XCode will produce a warning for "Local declaration of 'var' hides instance variable" when I try to use it:
//MyClass.h
...
#interface MyClass : NSObject
{
NSString *var;
}
...
//MyClass.m
...
- (void) doStuff
{
NSString *var = #"Hello World";
NSLog(#"%#",var); // Warning thrown on this line
}
So far this is what I would expect. However, if var is redefined in a deeper scope, such as an if block or for loop, XCode allows it, and the outer declaration is silently ignored:
NSString *var = #"Hello World";
if (TRUE)
{
int var = 0;
NSLog(#"%d",var); //prints '0', No errors or warnings
}
NSLog(#"%#",var); //prints 'Hello World'
Why is the last example silently allowed, but the other two are caught? Is there some option or flag I can toggle in XCode so that an error or warning would also be created in the last example? If XCode won't catch it for me, is there some code I could write to make sure variables are never redefined? Or is it just my responsibility to make sure I'm not re-using my variable names?
In the build settings (Xcode 5 & 6, at least) you can set a warning for Hidden Local Variables to YES.
The last example is behavior that Objective-C inherits from standard C. A variable's scope is determined by the bracing level. It's been that way since the earliest days for C. It's called variable shadowing, and it's actually pretty useful in ensuring that code keeps working even in the face of API changes in system libraries.
As far as why it's allowed, but the earlier examples aren't, that's a consequence of how Objective-C implements instance variables. The instance variables are essentially treated as local variables of each of the class's methods. So when you declare a local variable in a function that shadows an instance variable, it gets flagged as an error. Basically the first and second cases are treated as equivalent.
To get a warning for these cases, set the LLVM warning option Hidden Local variables to Yes.

weak definition of a bool in block

To define a weak references for objects in block i use something like this
MyViewController *__weak weakSelf= self;
UILabel *__weak weakLabel=ALabel;
///the block code with some examples
up2.completionBlock = ^(NSDictionary *headers, NSString *responseString) {
[weakSelf aMethodInTheController];
[weakLabel setHidden:NO];
};
I have problem with a bool, how i can declare a weak reference to a bool to avoid the warnings "capturing self strongly in this block is likely to lead to a retain cycle" ?
Not works with:
Bool *__weak weakFlag=Aflag;
Well, it's not obvious what you are trying to do here.
There are two possibilities. Perhaps you need to pass a parameter to the block. So there is a variable of type bool or BOOL (they are similar for the purposes of this question) and you want to use it in the block.
Then, good news! You don't need anything at all. Just declare
BOOL some_bool = (YES or NO or some calculation);
and use it later in the block. This works because Boolean types are primitive (they are some kind of integer) and not smart enough to participate in memory management. So the compiler doesn't worry much; it just grabs the value of this variable when the block is created and copies it into the block.
Here's the relevant documentation:
Only the value is captured, unless you specify otherwise. This means that if you change the external value of the variable between the time you define the block and the time it’s invoked, ...
Alternatively, perhaps you want to have a variable which can take logical values and which can be changed by some other object in the time between you create the block and the time when it is run. In that case you need to
wrap boolean into NSNumber
store the strong reference to this NSNumber somewhere in your object
pass it as a weak pointer to the block
E.g.
// somewhere in the interface
#property NSNumber *someImportantFlag
__weak NSNumber *weakFlag = someImportantFlag;
... ^{ ... if(weakFlag.boolValue) ... weakFlag = #(NO); ...}
Thanks to the commenters who made me reread the question and my answer.

Correct way of setting a BOOL property

I have a BOOL property that I want to set in my class initializer.
#property (assign, nonatomic) BOOL isEditMode;
- (id)init
{
. . .
[self setValue:NO forKey:isEditMode];
return self;
}
The compiler gives me an "Incompatible integer to pointer conversion" warning. What am i doing wrong here?
The Key-Value Coding method setValue:forKey: only accepts objects as arguments. To set a BOOL, you need to wrap the number in a value object with [NSNumber numberWithBool:NO]. But there's little reason to do that. Key-Value Coding is a roundabout way to accomplish this. Either do self.isEditMode = NO or just isEditMode = NO. The latter is preferable in an init method (because setters can run arbitrary code that might not be desirable before an object is fully set up).
But to elaborate on the first point: The reason Key-Value Coding works this way is because the type system can't represent an argument that's sometimes an object and at other times a primitive value. So KVC always deals with objects and just autoboxes primitive values as necessary. Similarly, if you do [yourObject valueForKey:#"isEditMode"], you'll get back an NSNumber object wrapping the real value.
The correct syntax to set a property is just
self.isEditMode = NO;
If you want to use -setValue:forKey: you'd have to write it as
[self setValue:[NSNumber numberWithBOOL:NO] forKey:#"isEditMode"];
However, there's absolutely no reason to do this in your situation.
That said, since you're in an init method, I would strongly recommend avoiding any property access whatsoever and instead using the ivar directly, as in
isEditMode = NO;
This avoids the possibility of an overridden setter being called (either in this class or a subclass) that makes the assumption that the object has already completed initialization. For this same reason you also want to avoid property access inside of -dealloc.
You can just assign the value directly:
isEditMode = NO;
I think you mean:
self.isEditMode = NO;
If your code does indeed compile (I'm pretty new to Objective-C so I don't know) setValue probably takes a pointer to a string (#"isEditMode", e.g.) and not some other type (isEditMode, e.g.).

Why shouldn't I use the getter to release a property in objective-c?

I was told by a fellow StackOverflow user that I should not use the getter method when releasing a property:
#property(nonatmic, retain) Type* variable;
#synthesize variable;
// wrong
[self.variable release];
// right
[variable release];
He did not explain in detail why. They appear the same to me. My iOS book said the getter on a property will look like this:
- (id)variable {
return variable;
}
So doesn't this mean [self variable], self.variable, and variable are all the same?
For a retained property with no custom accessor, you can release the object by:
self.variable = nil;
This has the effect of setting the ivar (which may not be called 'variable' if you have only declared properties) to nil and releasing the previous value.
As others have pointed out, either directly releasing the ivar (if available) or using the method above is OK - what you must not do is call release on the variable returned from a getter.
You can optionally write custom getter behavior, which may result in completely different behavior. So, you cannot always assume that [variable release] has the same results as [self.variable release].
As well, you can write custom properties without an exclusive ivar backing them... it can get messy fast if you start releasing objects from references returned by getters!
There may be additional reasons that I'm unaware of...
A typical getter will look more like this:
- (id)variable {
return [[variable retain] autorelease];
}
So if you use [self.variable release] you have an additional retain and autorelease that you don't really need when you just want to release the object and that cause the object to be released later than necessary (when the autorelease pool is drained).
Typically, you would either use self.variable = nil which has the benefit that it also sets the variable to nil (avoiding crashes due to dangling pointers), or [variable release] which is the fastest and may be more appropriate in a dealloc method if your setter has custom logic.
not all getters take this form:
- (id)variable { return variable; }
...that is merely the most primitive form. properties alone should suggest more combinations, which alter the implementation. the primitive accessor above does not account for idioms used in conjunction with memory management, atomicity, or copy semantics. the implementation is also fragile in subclass overrides.
some really brief examples follow; things obviously become more complex in real programs where implementations become considerably more complex.
1) the getter may not return the instance variable. one of several possibilities:
- (NSObject *)a { return [[a copy] autorelease]; }
2) the setter may not retain the instance variable. one of several possibilities:
- (void)setA:(NSObject *)arg
{
...
a = [arg copy];
...
}
3) you end up with memory management implementation throughout your program, which makes it difficult to maintain. the semantics of the class (and how it handles instance variables' ref counting) should be kept to the class, and follow conventions for expected results:
- (void)stuff:(NSString *)arg
{
const bool TheRightWay = false;
if (TheRightWay) {
NSMutableString * string = [arg mutableCopy];
[string appendString:#"2"];
self.a = string;
[string release];
// - or -
NSMutableString * string = [[arg mutableCopy] autorelase];
[string appendString:#"2"];
self.a = string;
}
else {
NSMutableString * string = [arg mutableCopy];
[string appendString:#"2"];
self.a = string;
[self.a release];
}
}
failing to follow these simple rules makes your code hard to maintain and debug and painful to extend.
so the short of it is that you want to make your program easy to maintain. calling release directly on a property requires you to know a lot of context of the inner workings of the class; that's obviously bad and misses strong ideals of good OOD.
it also expects the authors/subclassers/clients to know exactly how the class deviates from convention, which is silly and time consuming when issues arise and you have to relearn all the inner details when issues arise (they will at some point).
those are some trivial examples of how calling release on the result of a property introduces problems. many real world problems are much subtler and difficult to locate.

When to use brackets and when to use the period in Objective-C

I'm a new iPhone/Objective-C developer and as I'm going through different tutorials and open source code, I am having a bit of a problem understanding when to use the square brackets "[ ]" and when to use the period " . " for accessing properties/methods of an object.
For example, this code:
- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
[super setSelected:selected animated:animated];
UIColor *backgroundColor = nil;
if (selected){
backgroundColor = [UIColor clearColor];
} else {
backgroundColor = [UIColor whiteColor];
}
self.todoTextLabel.backgroundColor = backgroundColor;
self.todoTextLabel.highlighted = selected;
self.todoTextLabel.opaque = !selected;
self.todoPriorityLabel.backgroundColor = backgroundColor;
self.todoPriorityLabel.highlighted = selected;
self.todoPriorityLabel.opaque = !selected;
}
Why does [UIColor clearColor] get brackets, but todoTextLabel.backgroundColor get the period?
Could someone explain this easily for me?
The convention I have seen in new code is to use the dot for properties, and always use square brackets for messages/selectors (what you call methods). The dot was introduced in Objective-C 2.0, so the disagreement of information you find online is not entirely unexpected.
It's also entirely possible to use square brackets for everything, still (and I do):
foo = [myObject backgroundColor];
[myObject setBackgroundColor:foo];
is equivalent to
foo = myObject.backgroundColor;
myObject.backgroundColor = foo;
To reiterate, you should not be using the dot for messages, only properties.
To answer your specific question, [UIColor clearColor] belongs in brackets because it is not a property; it's actually a class message to UIColor (+(UIColor)clearColor).
You sound like you come from a Java world, so this might be helpful:
MyObject *foo = [[MyObject alloc] initWithAwesome:YES]; /* MyObject foo = new MyObject(TRUE); */
[foo doSomethingWithNumber:5 andString:"five"]; /* foo.doSomething(5, "five"); */
MyColor *bar = foo.faceColor; /* MyColor bar = foo.faceColor; */
MyColor *baz = [foo faceColor]; /* MyColor baz = foo.faceColor; */
foo.backColor = bar; /* foo.backColor = bar; */
[foo setUndersideColor:baz]; /* foo.undersideColor = baz; */
The "setXXX" and "XXX" messages come from synthesized dynamic properties, and are an Objective-C idiom. The "dot" is simply a shorthand for calling those methods, and is roughly equivalent.
EDIT: Now that I've got some upvotes, time to make some of you reconsider >:)
I never use dots, and neither should you.
I use dot notation for properties because,
for ( Person *person in group.people){ ... }
is a little easier to read than
for ( Person *person in [group people]){ ... }
in the second case readability is interupted by putting your brain into message sending mode, whereas in the first case it is clear you are accessing the people property of the group object.
I will also use it when modifying a collection, for instance:
[group.people addObject:anotherPerson];
is a bit more readable than
[[group people] addObject:anotherPerson];
The emphasis in this case should be in the action of adding an object to the array instead of chaining two messages.
Big Nerd Ranch has some thoughts on the dot notation that are worth reading.
There's also a rebuttal.
By (strong) convention, property accessors are written as methods named after the instance variable for the getter, and the (capitalised) instance variable name prefixed with "set" for the setter (so for instance variable foo you'd have foo and setFoo).
As others have pointed out, as of Objective-C 2.0, if you write object.foo, it will map onto method call [object foo] if getting or [object setFoo: arg] for setting. You can use either form, and some people continue to prefer the full method syntax even when using Objective-C 2.0 exclusively.
A separate, but related, addition to Objective-C 2.0 are the #property/#synthesize/#dynamic keywords for generating the getters and setters. You can mix and match these with dot notation - one does not require the other.
Yep, I just started learning this too:
Unlike other languages, syntax to invoke a method on an object is not objName.someMethod();
It's [objName someMethod]
The dot operator is used to either get or set the value of a property in a class. It's a short way of doing something.
The dot operator, as I have seen it, is always used on an instance of an object whereas the [...] can be used on either an instance of an object or statically (using the class name).
todoTextLabel can use the [] also but using the dot operator is just shorter hand...otherwise you would have to provide parameters, etc, and that's just longer notation.
Hope this helped.