Writing a killer iPhone or iPad app doesn’t require you to be a master of Objective-C, but the more comfortable you are with the language, the more you’ll enjoy it! Writing your own app may seem insurmountable at first, but if you start at the beginning with learning how and why a programming language works, then you can use those building blocks to create complex and amazing things, one step at a time.
Getting comfortable with the Objective-C programming language requires getting your hands dirty with some code. But you don’t want to dive right in without any prior knowledge, which is why we are here at Treehouse! This is the second in a series of posts that talk about the basics of Objective-C and how you can use it to write iOS apps. In the previous post we talked about the language itself and understanding variables, and in this post we will focus on an important basic concept known as methods.
Code Comments
But first, let’s start with a programming language feature that can at times be the single most useful feature to a programmer – Comments. A good comment can be worth the effort of a thousand programmers (though the reverse is also true…). It can be incredibly helpful to document the code that we write within the code itself. We basically leave notes to ourselves or other developers to explain what the code is doing.
We do this in Objective-C and other programming languages using comments. Comments in Objective-C code are lines of code that don’t have any effect on how the program runs. They are purely informational, meant to help us understand how the code works or is organized.
Single-Line Comments
Single line comments begin with two forward slashes: //
. Everything on the line after the forward slashes makes up the comment and is completely ignored by the program.
// This is a single-line comment NSString *badWord = @"Android"; // Only this part is a comment
Multi-Line Comments
Sometimes we want longer comments that span more than one line. In that case we use an opening marker to mark the start of the comment: /*
, and a closing marker to mark the end of the comment: */
.
/* This is a multi-line comment. Though only the opening * and closing markers are required, we often add an * asterisk at the beginning of each line to make it * more readable, and end the comment with the ending * marker on a new line. */
Methods, Messages, and Functions
The terms “method”, “messages”, and “function” all kind of refer to the same thing in Objective-C. You may hear them used interchangeably, though there are differences. I will stick with the terminology “calling a method” in this post. A method (or message or function) is a section of code that we can call from elsewhere in our code, and the method will perform some action or return some kind of result that we can use. Methods are used to organize our code into reusable (and understandable) chunks that save us a lot of time and energy.
Let’s illustrate this concept with an example. The NSString
class has a method called length
that gives us the number of characters in the string. The definition and code for this example might look like the following:
01 - (int)length { 02 int numberOfCharacters = 0; 03 // ... code to calculate the number of characters ... 04 return numberOfCharacters; 05 }
Line 1 declares the method named length
. The very first character is a dash: “-“. In Objective-C, method definitions begin with either a dash (-) or a plus (+). We’ll talk about this in more detail when we cover classes and objects, but the dash means that this is an instance method that can only be accessed by an instance of the class where the method is defined. A plus sign indicates that the method is a class method that can be accessed anytime by simply referencing the class.
In terms of our example, this means that we need to call the length
method on an actual string, an instance of NSString. This makes sense because we would only ever want to know the lengths of real, live strings. A class method (with the plus sign) would be used in other circumstances, like when we first want to create an NSString
instance variable, for example.
After the dash (or plus), we get a pair of parenthesis with an important word inside. This word is the return type of the method. In other words, it specifies what type of data will be returned by this method. In this example, we are going to return a simple int
because the length will simply be a number.
Some methods will do some work but won’t actually return any data. In these instances, we use a special keyword, “void,” to indicate that no data will be returned: (void)
. If we wanted to return a string instead, we would put “NSString *” in the parenthesis: (NSString *)
. (Remember from part 1 that the asterisk indicates a pointer, so we actually return pointers to the places in memory where strings are stored.)
Next we get the actual name of the method. In this simple example the name is simply “length”. Then we have a pair of curly braces that surround the lines of code that make up the method. If a method returns data (i.e. it’s return type is not (void)
), then the last line of the method must contain the return
keyword followed by the data to be returned. The return
keyword ends execution of the method, so any code written after that would not be executed.
Calling a Method (a.k.a sending a Message)
Okay, so we have defined a simple method. Now what? How do we use it? What good does that do for us?
01 NSString *emailAddress = @"ben@objectivecfun.com" 02 int stringLength = [name length]; 03 // stringLength will equal 21!
The example above shows how a method is used. Here we are calling the length
message on the emailAddress
variable, or more accurately, sending the length
message to the emailAddress
object.
A Quick Explanation of “Method” vs. “Message”
Objective-C is based on a message passing model that is kind like calling methods plus some other goodies. It’s essentially the same as calling a method like in many other programming languages, which is why they are often used interchangeably. Message passing is different in that any message can be sent to any object. It’s up to the object to handle the message or not. If it doesn’t handle the message, then nothing bad will happen; it will just return nil to the sender, or caller. This is different than the method model because, If a method is called on an object that doesn’t define the method, we end up with compile-time or run-time errors that stop us dead in our tracks.
01 NSString *testString = [emailAddress addSparkles]; 02 // testString will equal "nil" because, believe it or not, 03 // "addSparkles" is not a valid NSString method.
Okay, back to our discussion…
Remember that those square brackets are used to differentiate Objective-C constructs from plain old C code. The square brackets around name length
indicate the method call. The method calculates the length to be 21 and it is returned to where it was called from. We do something with this return value by storing it in a new int
variable named stringLength
. It’s as if 21 takes the place of [name length]
:
01 // We can basically replace the method call with 02 // the value it returns 03 int stringLength = 21;
Method Parameters
Methods will often include extra pieces known as parameters, which are sometimes referred to as arguments. Let’s work with a new example since length
doesn’t require any parameters. The method below simply adds two int numbers:
01 - (int)addX:(int)x toY:(int)y { 02 int sum = x + y; 03 return sum; 04 }
Let’s be honest; that looks a little crazy. If you are learning Objective-C after using another language (like JavaScript, for example), this can be a little hard to read and understand. Let’s break it down piece by piece. The first part of the definition, or method signature, is similar to what we saw for length:
- (int)addX
The dash means that this is an instance method, (int)
means that it will return an int
value, and the name starts with “addX”.
Parameters are specified with a colon after the name, a data type, and their own name.
:(int)x
This means that the first parameter of this method is an int
variable named x
.
Additional parameters are specified in the same way, but what is a little weird is that we also add a new piece to the name of the method. So we type a space and add the following:
toY:(int)y
The first part, “toY”, is actually part of the message name. The full message name is now “addX:toY:”. Reading it without the colons explains exactly what this method does, and the colons indicate where the parameters are set. The second parameter is very similar to the first; it’s an int
variable named y
.
To call this method, we simply plug in variables or values for the parameters. In the length
example above, the length
method was defined in the NSString class, which is why we called it on a string variable. (Or we could say that we sent the length
message to a string variable.) In this example, let’s pretend that the addX:toY:
method is defined in a GameScore class from a game, and that we have a variable named “score” that has GameScore as its data type:
01 int points = 100; 02 int newScore = [score addX:24 toY:points]; 03 // newScore now equals 124
Notice that we can use a literal value (24) or a variable that holds a value (points
) for either parameter. Also notice that the names of the parameters doesn’t matter in terms of calling the method. The names are used in the definition and are used in the code that makes up the method, but they have nothing to do with the code we write when we call the method.
What is the function of a “function”?
I mentioned “functions” at the beginning of this section, because like methods, they are reusable chunks of code that we call from other places. A very common example is the NSLog()
function that writes data to the operating system log:
NSLog(@"This is some string data being written to the log.");
Functions are the original “method” constructs from regular C. Their syntax is slightly different, though. In the NSLog example above, “NSLog” is the name of the function, and then its parameters are specified inside parentheses. Functions always end with parentheses, even if there is nothing in them. In this example we are passing one string parameter. The signature for this method would look something like this:
01 void NSLog(NSString *text) { 02 // Logging code 03 }
Notice that functions can be called from anywhere without any reference to the class where they are defined. Our previous examples were called on variables: emailAddress
and score
. Those variables framed the context in which the method was supposed to act. Functions can be called from anywhere and simply act on the data passed into them.
As a geeky bit of trivia, any Objective-C method can be rewritten in C syntax as a function. Remember again from part 1 that Objective-C maintains all the syntax from C and just adds object-oriented features as a thin layer on top of the world of C code.
Major Benefit of Using Methods
Imagine that we have five different NSString variables that we need to know the lengths of. If we didn’t have a length
method to use, we’d have to write the code to calculate the length five different times. But by creating a reusable method, now we only need one line of code each time we want to determine the length of a String value. Programming is all about efficiency, so use methods whenever possible to organize your code and save yourself work.
A side benefit that comes out of this is that our code becomes much more readable when we use methods effectively. With intuitive names and clear actions, using methods reduces many lines of spaghetti code that are hard to read through and understand into simple and elegant code that we can understand quickly. We spend a lot of our time reading code as programmers, whether we are troubleshooting our old code, trying to remember what we wrote a long time ago, or trying to understand or fix somebody else’s code.
For example, there is a lot of magic that happens behind the scenes of these three lines of code, but I bet you can figure out what they do:
01 NSURL *url = [NSURL URLWithString:@"http://teamtreehouse.com"]; 02 NSString *htmlData = [NSString stringWithContentsOfURL:url]; 03 NSLog(htmlData);
More to Come!
We’re starting to really understand how Objective-C is organized, but we still have a lot of important programming concepts to cover, like what objects and classes are and why they are used. Once again, you can practice all of the stuff we talked about in this post in any of the iOS projects in the Treehouse Library, which all include interactive Code Challenges that allow you to write some Objective-C code in the browser. Happy coding!