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.


Solution 1:

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.

Solution 2:

Dot notation is just shorthand for a specific kind of method--namely, accessors. You may use it in the following cases:

  1. When setting a property: foo.bar = 3; is equivalent to [foo setBar:3];.
  2. 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.

Solution 3:

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.

Solution 4:

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.

Solution 5:

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.