NSArray (and other Cocoa types) #property values - objective-c

While in the process of debugging code written by a co-worker, I stumbled across the following that has me mystified:
NSMutableArray *array = [NSMutableArray array];
NSUInteger arrayCount = array.count;
Why does this work? It also works for NSDictionary and other types, but nowhere in the documentation nor Cocoa headers can those #property definitions be found.
Googling for "NSArray property" doesn't yield many useful results, so I'm reaching out to SO for what will surely be a very embarrassing question.

It works because dot syntax has nothing to do with properties. It is simply syntactic sugar (though I don't like it, so perhaps it's "syntactic salt").
When you use dot syntax as the rvalue to an expression (or the expression to the right of the equal sign), it simple turns:
bar = myObject.thing;
Into
bar = [myObject thing];
When the dot is to the left of the equal sign (as an lvalue), it turns it into the setter. So:
myObject.thing = 42;
Becomes
[myObject setThing:42];
So yes, you can do things like myObject.retain. But you should never ever do that. You should only ever use dot syntax as accessors to declared properties (ie, things that have been explicitly declared via #property). <insert remark about how you should never use dot syntax at all.>
For more information, checkout out the documentation on dot syntax (specifically the "incorrect use" section).

the dot syntax is actually just an alternative for accessing methods that either take no parameter and return a value like array.count. It is bad form to actually access the methods in that way.
It can also be used for things like [object setValue:(id)something] and access it by doing object.setValue = something;

Related

Can't find the source of this "Expected Identifier" error, any thoughts?

I'm very new to Objective-C and programming in general and I'm having some difficulty solving a strange error I'm getting in my code. I've rechecked my code line-by-line but no matter what I do I get an "Expected Identifier" error on this one line.
NSString *text = [NSString stringWithFormat:#"Your total is $%.2f", [self.cartTotal]];
I've retyped the line several times to make sure that I wasn't missing any typos, but a little red arrow is pointing to the first closing bracket.
Take [self.cartTotal] out of the brackets. They're unnecessary here.
Should be:
NSString *text = [NSString stringWithFormat:#"Your total is $%.2f", self.cartTotal];
To help understand the error (assuming you're coming from a language like Java or C++), what you've written is the equivalent to writing this in say Java:
this.cartTotal.
Notice the hanging dot at the end? That's what you've done here basically. In Java, that dot suggests you're calling a method on whatever object cartTotal is, or access a public variable on that object. I'm not sure what a Java or C++ error message would say here, but this is the equivalent scenario.
Given #GregParker's excellent comment...
You created cartTotal by way of a #property.
#property double cartTotal; // or something like this
This creates three things:
A setter
A getter
An instance variable
The setter is accessed in two ways:
[self setCartTotal:value];
Or:
self.cartTotal = value;
These both do the same thing.
The getter is likewise accessed in two ways:
[self cartTotal];
Or:
self.cartTotal;

Is it OK to use dot syntax to call methods?

I'm trying to learn how to develop using objective C and I read on this book that to access an ivar from a class using dot syntax (obj.var) you must implement these vars using #properties, however I've tried using this kind of access without defining #properties for these vars and it seemed to work normally.
How does this kind of access works ? Is it a good practice to use it like it's in Java ?
Example:
ComplexNumber *c1 = [[ComplexNumber alloc]init];
c1.realPart = 3;
c1.imaginaryPart = 2;
ComplexNumber's methods:
- (double)modulus;
-(void)setRadius:(double)aRadius phase:(double)aPhase;
-(void)print;
-(double)realPart;
-(double)imaginaryPart;
-(void)setRealPart:(double)value;
-(void)setImaginaryPart:(double)value;
A property is just a promise that the class implements certain methods. The dot syntax is simply translated into calls to methods with the appropriate name, depending on what the code is doing:
b = a.foo; // becomes 'b = [a foo];'
a.foo = b; // becomes '[a setFoo:b];'
So you can actually get away with using dot syntax to call methods even when those methods aren't properties. That can be sort-of okay if the method represents something that works like a property, such as accessing the length method of an array:
len = myArray.length // becomes 'len = [myArray length];'
But mostly you shouldn't do it. It takes something that's not a property and makes it look like a property. It might work, but it's going to confuse people who look at the code (including the future you). You definitely shouldn't use it to call methods that have side effects because property accessors aren't expected to have side effects.
No its not a good practice, you technically can access zero argument methods using dot syntax but now Xcode will warn you about doing this. This is against Apple's coding guidelines.
Bracket syntax should be used for calling methods.

Dot Notation vs Method Notation

I'm diving into iOS programming and I'm having difficulty getting my head around the idea of Dot Notation and Method Notation.
As far as I understand it, Dot Notation can be used to invoke setters/getters on properties and is much more cleaner to write/read. Method Notation is used to send messages to objects to manipulate them etc.
Could someone give me a simple explanation as to why the following two statements are essentially different and one will compile but the other will instead fail due to a syntax error.
- (IBAction)digitPressed:(UIButton *)sender
{
NSString *digit = [sender currentTitle];
self.display.text = [self.display.text stringByAppendingFormat:digit];
self.display.text = self.display.text.stringByAppendingFormat:digit;
}
Thanks.
You're entering into Objective-C development at an interesting time where old syntax is being used with new syntax. Dot syntax is syntactic sugar and there are some cases where you can use it but you should not.
The following is invalid syntax. Anything where you'd use a colon (besides setters or getters), you won't use dot notation.
self.display.text = self.display.text.stringByAppendingFormat:digit;
Also, you would use stringByAppendingString, not stringByAppendingFormat
You use dot notation for accessing variables, not for calling actions that will have effects.
Correct:
self.foo.attributeOfMyClass
Incorrect:
self.foo.downloadSomethingFromAWebsite
Ensuring you always use dot notation for accessing property values and you always use bracket notation (even when you don't have to) for calling action methods, your code will be much clearer upon a glance.
Dot notation is just shorthand for a specific kind of method--namely, accessors. You may use it in the following cases:
When setting a property: foo.bar = 3; is equivalent to [foo setBar:3];.
When requesting a property: in any case except the one above, foo.bar is equivalent to [foo bar].
Dot notation is only shorthand--there is nothing magic about its relationship to properties. You could theoretically use dot notation to send any message that takes no arguments (foo.doSomething), but this would be very very bad style, as dot notation is intended for properties. Also note that if dot notation vs. square brackets is confusing you while you're learning, it's a perfectly valid choice to avoid dot notation altogether. It's just one shortcut you may use for accessors, if you like.
Actually, your second statement is not correct. Objective C way to invoke methods (messages) is using the [instance message] syntax.
As you said, the dot notation is just to call getters and setters on class properties, but not messages, that's why your second statement is not correct. The two lines you may wanted to compare are:
self.display.text = [self.display.text stringByAppendingFormat:digit];
[[self display] setText:[[[self display] text] stringByAppendingFormat:digit]];
Note that the message stringByAppendingFormat has to be called the normal way.
The dot notation is just to write faster and not so many brackets, but it will execute exactly the same instructions once compiled.
Another reason for using selector notation rather than dot notation is due to the dynamic language features in Objective C. As an example, consider the following:
NSString *s = #"Hello World!";
NSLog(#"Length is %d", s.length);
This works as we would expect. However, objects in Objective C may be passed around with type id. Consider the following:
id s = #"Hello World!";
NSLog(#"Length is %d", s.length);
This won't compile, as id doesn't have a property called length. The following will work, however:
id s = #"Hello World!";
NSLog(#"Length is %d", [s length]);
The reason this works is that Objective C knows about NSString, and so knows that there is some object type that responds to the selector length. Of course, if you try the following:
id s = [[UIView alloc] init];
NSLog(#"Length is %d", [s length]);
Your code will compile correctly, but a runtime exception will occur (unrecognized selector sent to instance) as UIView does not have a length selector.
Let's say we have the class Class with the variable variableOne we are going to use both notations.
Dot notation is the purest way to access a variable. It is also the way that bracket notation is most likely doing it behind the scenes. By typing Class.variableOne... variableOne is a part of Class and the "." after the class tells the compiler that it would like to access a part of the class--either a variable or a method.
Bracket notation is uses a method to access the variable. Let's say...
-(int) setVariable:x {
self.variableOne = x;
}
-(int) showVariable {
return self.variableOne
}
So when you're using bracket notation to set the variable [variableOne setVariable:5] or displaying the variable [variableOne showVariable] it calls the appropriate method.
This is a very simple way to think of the difference, I realize another answer has already been accepted but perhaps this answer will explain it for someone who didn't understand another answer.
When your code gets compiled, clang actually first takes all of your dot notation and turns it into method/bracket notation, so self.display and [self display] are exactly the same. Dot notation is actually fairly new as of Objective-C 2.0. It's simply for convenience.
Dot notation can only be used for properties, because doing something like you tried to do (which will not compile) gets cumbersome:
self.display.text.stringByAppendingFormat:digit;
It also wouldn't work for methods that take multiple arguments since you'd need to put spaces between arguments and suddenly the line of code would look awkward and hard to read.

Mixing C pre/post increment/decrement with Objective-C dot operator works?

Say I have a class with a scalar property type:
#property (nonatomic, assign) int myInt;
And for clarity, synthesized like:
#synthesize myInt = _myInt;
If someone had asked me if the following line would work:
self.myInt++;
I would have said "No". The rationale being that we all know that the dot operator is just syntactic sugar for calling a compiler-generated getter method. So that line is literally:
[self myInt]++;
If you type that second line into Xcode, it won't compile, stating: "Assigning to 'readonly' return result of an objective-c message not allowed". This makes perfect sense, and it's what I would have expected. Even if that compiled, I would have expected the outcome to increment a copy of the backing ivar on the stack, not the ivar itself.
But, the instruction self.myInt++ does compile, and it works. It works just as if that dot operator were directly accessing _myInt. By supplying my own getters and setters, I can see that both the getter and the setter are used in the process, in that order, like it was actually:
[self setMyInt:[self myInt] + 1];
So, is this an exception to the rule that the dot operator is exactly the same as a method call, or are the {--, ++, +=, -=} operators given special attention by the Objective-C compiler when used with dot notation? I've always thought of them as a C language features with no special considerations for Objective-C. I could see that simple line being very confusing to someone unfamiliar with Objective-C dot notation.
You can look at the assembler output and see that it generates two _objc_msgSend calls.
I'd guess it's more a case of applying the rule that a++ is syntactic sugar for a = a + 1

Objective-C dot syntax tricks for when Key-Value won't work?

I'm iterating through some objects and trying to set some properties that, apparently, don't like Key-Value coding. so I'm unable to create a string at runtime to represent the "key".
This line of ViewController won't compile:
[self setValue:offsetX forKeyPath:[NSString stringWithFormat:#"myView%d.center.x", anInt]];
but I can set these properties with dot notation in a ridiculous switch statement:
myView1.center.x = offsetX;
Is there another way to go about this? perhaps create an accessor like myView(i).center.x ? Knowing full well it was going to be futile, i even tried: [NSString stringWithFormat:#"myView%d", anInt].center.x
to no avail...
The reason it wont compile is presumably because offsetX is an int or float, not an NSNumber (it would be helpful to give the compiler error message in your question).
However KVC and setValue:forKeyPath: is very clever and will automatically convert from an NSNumber for you, so use:
[self setValue:[NSNumber numberWithInt:offsetX] forKeyPath:[NSString stringWithFormat:#"myView%d.center.x", anInt]];
(or numberWithFloat as appropriate).