Sei sulla pagina 1di 37

OBJECTIVE - C CLASSES

Welcome to my series on coming to grips with the awesome language that is Objective-C. Throughout this small series of articles, my aim is to take you from no prior experience with Objective-C to using it confidently in your own applications. This isnt a rush job so dont expect to just skim through the basics and be away well be going through not just the bare essentials, but also the best practices you can apply to ensure your code is the best it can be. Lets jump straight in!

What is Objective-C?
If youre reading this series then Ill hazard a guess that you already know, but for those of you who dont, dont worry as by the end of this part youll know what it is back-to-front and inside-out. Objective-C is an object oriented language which lies on top of the C language (but I bet you guessed that part!). Its primary use in modern computing is on Mac OS X as a desktop language and also on iPhone OS (or as it is now called: iOS). It was originally the main language for NeXTSTEP OS, also known as the operating system Apple bought and descended Mac OS X from, which explains why its primary home today lies on Apples operating systems. Because Objective-C is a strict superset of C, we are free to use C in an Objective-C file and it will compile fine. Because any compiler of Objective-C will also compile any straight C code passed into it, we have all the power of C along with the power of objects provided by Objective-C. If youre a little confused at this point, think of it this way: everything C can do, Objective-C can do too, but not the other way around.

What will I need?


Throughout this series, we will not focus on building applications for the iPhone. Instead, we will concentrate more on the language itself and for this reason all you will need is a Mac with a compiler such as GCC. If youve installed the developer tools from Apple (Xcode, Interface Builder, etc), then GCC should already be installed. If not, then head to Apples developer website and get yourself a free copy. As far as prerequisites go, while I dont expect you to have a full background in computer science, some knowledge of programming in general or of C in particular would definitely be a bonus. If you dont have much prior programming experience, dont worry -youll pick it up in no time! If youre running Windows (which is unlikely as this tutorial is aimed at iPhone developers) you can still compile Objective-C on your system using a compiler such as CygWin or MinGW. This tutorial series is catered to Mac users, but if you are using Windows and encounter any problems then be sure to leave a comment and Ill see if I can help.

Compiling your code


Before you can see your code in action, you need to be able to compile it into something executable. Hopefully you now have your copy of GCC ready. Compiling is really easy, a simple one line command. NOTE: Compiling is the process of translating a high-level computer language, like Objective-C or PHP, into a low-level machine code that can be processed by a computer when the program is executed. All the programs that we see running in our fancy Mac OS operating system consist of a series of instructions that are visually displayed to us in a GUI, or Graphical User Interface. In contrast to the GUI program interaction with a mouse that most of us are familiar with, it is possible to issue commands directly to the operating system through a text-based interface known as a terminal or command line. The command line application in Mac OS is called Terminal and can be found in Applications -> Utilities. Go ahead and open Terminal now (you can also search for it in Spotlight). Terminal has several basic commands you should be aware of in order to properly utilize it. One of the most important commands to know is cd, which stands for change directory. This command allows us to change where in the filesystem Terminal is reading from. We cant just tell Terminal to compile our file if we dont show it where the file is first! To switch to a desired directory, you can use a full path such as: 1. cd /Users/MyName/Desktop/Test You can also use relative paths, allowing you to only type a single folder name in some cases. For example, if youre already in your Desktop folder, you could simply type: 1. cd Test to get to the Test folder. What if you want to see where you currently are? The immediate folder name is displayed before the prompt (the bit where you type). For example, if your prompt says Dan- WalkersMacBook: Desktop iDemonix$ I can assume Im in the Desktop folder. If you arent sure, you can also type pwd to display the absolute filepath of the current location. If you want to list what files and folders are in the current folder, use the list command: ls. Finally, if you wish to go up a directory to a parent folder, type cd .. . So, if we were in the Test folder, which is inside the Desktop folder, but we wanted to go to the Desktop folder instead, we could type cd .. to go up to the parent directory, Desktop. If we wanted to get to the home directory we would type cd ../.. to go up two levels. Alternatively, to get to the home directory you can just type cd ~ from anywhere. When using the Terminal application, compiling looks like this: 1. gcc inputfile.m -o outputfile

Youve probably already guessed how it works: inputfile.m contains our code (.m is the extension used for Objective-C files) and -o tells gcc we want our executable to be called whatever we specify next, which in the example above is outputfile. To run our creation after compiling, we simply type: 1. ./outputfile Simple. When you compile, the compiler will generate any errors, notifications or warnings related to the syntax of your code. Errors generated when compiling are understandably referred to as compile-time errors, and this is often the most stressful part of writing an application (especially when your code isnt compiling because you put a single character in the wrong place or forgot to end a line with a semi-colon). Compiling can also take time when youre writing large applications consisting of multiple files, which is also another reason why compiling can be a tedious experience. This fact has led to a ubiquitous programmer joke often seen on the t-shirts of men with unkempt beards: Im not slacking off. My code is compiling.

The Basics
Objective-C itself isnt that hard to learn. Once you get to grips with the basic principles, you can pick the rest up as you go along pretty easily. You do need to have an understanding of the fundamentals of C programming though, and that is what the rest of this tutorial will cover. Lets look at a basic application in C:

1. #include <stdio.h> 2. int main(){ 3. printf("Hello World\n"); 4. return 0; 5. } All this application will do when you run it is display the string Hello World in Terminal and exit. NOTE: Curious about the return 0 statement? Because we told the compiler that the function main() will return an integer, we return the constant integer value 0 at the end of the function. By convention, returning 0 signals to the calling program that our program finished execution without any errors. To try this for yourself, fire up Xcode and make a new Objective-C class. Delete all the code Xcode gives you by default and stick the above code in. Once youve done that, you can compile it using Terminal. Open Terminal and change to the location where your file is, if you saved to the desktop then simply type cd desktop so that Terminal is now reading from your Desktop. Then type this command:

1. gcc program1.m -o program1 Your program should compile with no errors. To run it, simply type: 1. ./program1 Then hit return. Awesome, so what actually happened there? Well, first we imported a library called stdio which manages the standard i/o (input output) functions, like printf(). We then create a function called main which should return an int or integer which is basically a number with no decimal point. We then use the printf() function to output Hello World in to terminal. The \n we use tells Terminal to put a newline after the text. Finally, we return 0 (remember we said main should return an integer) which tells the operating system everything went fine. We use the name main because this is triggered automatically when the program is executed. So far everything should be pretty simple: we wanted to write some text to Terminal, so we imported a library with a function for writing text, then we used a function from that library to write the text. Imagine that what you import is a physical library and printf() is one of the books available.

Variables
Soldiering ahead, were now on to variables. One of the fundamental things we need to be able to do in our applications is temporarily store data. We do this using variables, which are containers that can hold various types of data and be manipulated in various ways. We use variables to store all sorts of data, but we must first tell the compiler what were going to store in it. Here are several of the most important variables that you should know about for now:

int for storing integers (numbers with no decimal point) char for storing a character float for storing numbers with decimal points double same as a float but double the accuracy

When were not using variables, were often using constants. A constant will never change: we always know what the value will be. If we combine constants we get a constant expression, which we will always know the result of. For example:

1. 123 + 2 = 125 This is a constant expression, 123 + 2 will always equal 125, no matter what. If we substituted a constant for a variable, the new expression would look like this: 1. 123 + i = ?

Because i is a dynamic variable, we do not definitely know the result of this equation. We can change i to whatever we want and get a different result. This should give you an idea of how variables work. One thing we still need to know is how do we display variables like we displayed Hello World above? We still use the printf() function, except it changes a little this time: 1. #include <stdio.h> 2. int main(){ 3. int someNumber = 123; 4. printf("My number is %i \n", someNumber); 5. return 0; 6. } What weve done here is told the function printf() where we want our integer to appear, then where it can be found. This is different to a lot of languages such as PHP where you could just place the variable in the text. We are not just limited to just one variable in printf(). The function can accept multiple parameters separated by commas, so we can pass in as many as we have formatting signs for in the text. Above we use %i as a formatting sign because we were including an integer. Other variables have their own format specifiers:

%i integer %f float %e double %c char

One thing I want to touch on before we move on is the char type. A variable of type char can only handle single characters, when thats all we need this is great, but if we need a string of text its pretty useless. To get round this, we use something called a character array. Imagine you have a sentence that is 11 characters long (like Hello World dont forget to include the space), a character array is like having 11 chars but all glued together. This means that the value of the character array overall is Hello World but char[0] is H. In brackets is the char youre after, because we put 0 we get the first character. Dont forget that counting in arrays usually starts from 0, not 1.

Conditionals
When an application needs to make a decision, we use a conditional. Without conditionals, every time you ran your application it would be exactly the same, like watching a movie. By making decisions based on variables, input or anything else, we can make the application change this could be as simple as a user entering a serial number or pressing a button more than 10 times. There are a few different types of conditionals, but for now were just going to look at the most common and basic: the if statement. An if statement does what it sounds like, it checks to see if something is true, then acts either way. For example:

1. 2. 3. 4. 5. 6. 7. 8. 9.

#include <stdio.h> int main() { if(1 == 1) { // This is always true // Do some stuff here } return 0; }

If 1 is equal to 1, then whatever is between the brackets is executed. You might also be wondering why we used two equals signs instead of one. Using two equal signs is an equality operator, which checks to see if the two are equal to each other. If we use a single equal sign then were trying to assign the first value to the second value. Above, since 1 will always be the same as 1, whatever is in the brackets would be executed. What if we wanted to do something if this wasnt true though? Thats where else comes in. By using else we can run code when the if conditional returns false, like so: 1. int main(){ 2. if(1==1){ 3. // Do some stuff here. 4. } 5. else{ 6. // The universe is broken! 7. } 8. 9. return 0; 10. } Of course, in real life, we wouldnt be checking to make sure 1 is the same as 1, but the point is made. Consider an application that closes if you press the close button three times (annoying but relevant). You could check in the brackets to see how many times it has been pushed. If it is lower than 3, then your else block could execute code to tell the user how many more times the button must be pushed to exit. Well look at conditionals more when we come to use them in our applications further along in the series.

Loops
Now lets investigate a programming loop. Loops, as the name suggests, let us loop through a piece of code and execute it multiple times. This can come in very handy in situations such as populating a list or repeating a piece of code until a conditional returns true. There are three types of loops, in order of most common: for, while, and do. Each one is used to repeat execution of a block of code, but they function differently. Here are examples of each:

1. // if loop 2. int main () { 3. int i = 9; 4. int x = 0; 5. 6. for (x = 0; x < i; x++){ 7. printf("Count is: %i\n", x); 8. } 9. 10. return 0; 11. } This may look a little complex at first, but it really isnt. In the parentheses after for is the initiator, a conditional, and the action. When the for loop starts it executes the initiator, which in our case above sets x to 0. Each time the loop runs (including the very first time) it checks the conditional, which is "is x smaller than i?" Finally, after each loop through the code, the loop runs the action - which above increments x by one. Simple. Since x is increasing by one each time, x will soon no longer be less than i and the loop will finish and the program will carry on running. 1. // while loop 2. int main () { 3. int x = 0; 4. while (x < 10){ 5. printf("Count is: %i\n", x); //Watch OUT! Something is missing. 6. } 7. 8. return 0; 9. } Similar to the for loop, the while loop will execute the code between the brackets until the conditional is false. Since x is 0 and we don't change it in the code block, the above would run forever, creating an "infinite loop." If you wish to increment x, then in the case of our while loop you would do this between the brackets: 1. // while loop 2. int main () { 3. int x = 0; 4. while (x < 10){ 5. x++; 6. printf("Count is: %i\n", x); 7. } 8. 9. return 0; 10. } The do loop is essentially the while loop, except the conditional runs after the block of code. What this means is when using a do loop, the code is guaranteed to run at least once:

1. // do loop 2. int main () { 3. int x = 0; 4. do { 5. x++; 6. printf("Count is: %i\n", x); 7. } while(x < 10); 8. 9. return 0; 10. }

Pointers
Pointers can cause a lot of confusion with newcomers to programming or just newcomers to C. It is also not immediately clear to some people how they are useful, but youll gradually learn this over time. So, what is a pointer? As the name implies, pointers point to a location. Specifically, locations in computer memory. Think of it like this, when we create a variable (let's say it's an integer called foo as is so popular with programming theory) and give it a value of, for example 123, we have just that a variable with a value of 123. Now, if we setup a pointer to foo, then we have a way of indirectly accessing it. That is, we have a pointer of type int that points to foo which holds the value '123.' This would be done in code like so:

1. int foo = 123; // This is an integer variable 2. int *ptr = &foo; // This is a pointer to an integer variable Clear as mud? Dont sweat it. Pointers are hard - often considered the hardest thing to learn when picking up the C language. Pointers will eventually become second nature to you though, and there will be more on pointers within Objective-C further in this series.

Wrapping Up
You've just been given a crash-course overview of the C language fundamentals. This part of the series was intended to be a quick primer on C to get you ready and prepared for the rest of the series, and should have been especially useful to those who are already familiar with programming in another language. If you are new to programming in general or are still in doubt about any basic of C, re-read the above and feel free to leave questions in the comments. Before next time, be sure to try and compile your own programs using the code above. Set yourself small challenges, such as making a loop execute 10 times and count each time through the loop using printf. Theres no harm in trying and experimenting, if it goes wrong then its probably even better as itll get you on the right track to troubleshooting your own code.

Challenge
For this week, we will end on a simple challenge. You are to create three programs that count to 10 using each type of loop. Since we will use loops often in Objective-C, its good that you learn to create them by heart. That should be pretty easy, so try to count down from 10 to 1 afterwards (if ++ increments by one, what could be the code to decrement by 1?).

Next Time
In the next installment of this series, Ill provide an overview of how Objective-C works. Well also look at object orientated programming and its uses, as well as really drill down into classes, instances, methods, inheritance and more. Next week should really help you to understand what makes Objective-C such a great language and why it really extends the C language in so many useful ways.

Any Questions
If you have any questions, you can either leave a comment below where Ill try and keep checking or you can shoot me a message on Twitter (http://www.twitter.com/iDemonix) where Ill get back to you ASAP.

Welcome to part two of this introductory series on Objective-C. After spending last week reviewing the fundamentals of the C language upon which Objective-C is built, this week we will transition to focusing on what makes Objective-C such a great language for software development. Specifically, we will discuss the fundamentals of Object Oriented Programming (OOP) and demonstrate how to create a class and send messages to objects in Objective-C.

Object Orientated Programming


Why do we have Objective-C? Why not just use the underlying C language? The reason we have Objective-C is to give us an object oriented playground within which to build our applications. OOP is a programming paradigm that attempts to allow developers to think about software design in terms of objects and attributes instead of variables and functions. Specifically, OOP attempts to obtain data abstraction, encapsulation, modularity, polymorphism, and inheritance. The topic of OOP could easily fill a book (or a tutorial series) on its own, so instead Ill introduce you to the basic principles by way of example. Imagine that you have a car. You can think of your car as an object. There are many other cars in the world and you might even own more than one. Your car has various properties to it: make, model, color, engine type, and many more. In Object Oriented Programming terms, we would call the abstract concept of a car a class and the individual car that you own an object or instance (instantiated object) of the class. When a new car is manufactured, a new instance of the car class is instantiated (or created) and given its own set of properties. Still a little fuzzy? Another great analogy is that of the cookie and the cookie cutter. The class is the cookie cutter, and the object is the cookie. So, why think in terms of objects? One of the best reasons is because this is how your brain naturally conceptualizes life in the real world, and there are many benefits to being able to abstract software development in similar terms. Classes (and hence objects) are made up of methods and attributes. If you come from another programming language, you may be more familiar equating methods with functions and attributes with variables. We will discuss each in turn next.

Methods
So we have an instance of a car, now that what do we do with it? Well, we drive it and fill it with petrol, among other things. Driving and filling with petrol apply only to the cars that we use, meaning that when we fill up a car or drive a car, we are only impacting one instance, and not all the cars in the world. Therefore, filling up the car instance is considered an instance method. Its something we do to our instance and only our instance. On the other hand, if we ask the original car class how many colors of car are available, this is a class method because we are no longer only talking about the car we drive around but all cars in general. Many of these principles become more clear with use, so lets look at a little bit of syntax.

In Objective-C, we call object methods by passing messages. When we want to know how much gas is in our instance of car, then we send a message to our instance and the message is the method we want to apply. Programmatically it looks like this: 1. [recipient message]; The brackets indicate we are sending a message. The first parameter is who should receive this message and the second parameter is what the message actually is. Finally, we end with a semi-colon as is common to most programming languages. So, with our previous example in mind, this is how we would interact with our instance of car to add gas to the tank; 1. [dansCar addGas]; The example above assumes that we have instantiated an instance of the Car class and named it dansCar. We then pass the addGas message to the object dansCar, which is the equivalent of calling a function. In another language, this line might look like: 1. dansCar.addGas();

Attributes
Lets say our car class has a gas tank thats stored as a percentage. For example, if the gas tank is at 50% then it is half-full and if it is at 100%, it means it is full to the brim. Now, if we want to know how much gas is in the tank, we dont just directly take that information from an attribute. Instead, we would use an accessor method to access the internal variable for us. Likewise, when we want to fill the tank, we dont just give the gas tank attribute a new percentage, we use a setter to update the attribute for us. This process is known as data encapsulation. What we mean by data encapsulation is that data is contained (so to speak) by methods meaning to access it we need to use methods. Some of you who have programmed in other languages and havent heard of data encapsulation may be wondering why we do things this way. The answer is that by encapsulating data, there is a nice cushion between the developer of a class and the user of a class. Because the class methods manage and maintains the attributes within the class, they can more easily maintain data integrity. Another major benefit is that when a developer distributes his class, the people using it dont have to worry about the internals of the class at all. A developer may update a method to make it faster or more efficient, but this update is transparent to the user of the class as he/she still uses the same method with no change to his/her code. This brings us nicely on to the next section were going to look at, which is how Objective- C separates interface from implementation.

Interface and Implementation

When you create or work with a simple class in Objective-C you will see that it, by default, has two files. One is the implementation file which is a file that ends with a suffix of .m and the interface file which is a file that ends with a suffix of .h.

Interface
1. #import <cocoa cocoa.h=""> 2. 3. @interface Car : NSObject { 4. 5. //This is where attributes go 6. float fillLevel; 7. 8. } 9. 10. //This is where methods go 11. - (void)addGas; 12. 13. @end 14. </cocoa> First of all, were importing Cocoa.h which is a standard library with a lot of reusable code that we can use inside our app. Next, were declaring that this is the interface for the Car, but were also putting NSObject into that declaration. Adding : NSObject means that the Car class inherits from the NSObject class. Well talk more about inheritance in a future tutorial. Our instance variable fillLevel is declared next, and we specify that it is of the float data type so we can easily represent a percentage. The next line declares our addGas method. The - indicates that this is an instance method, not a class method. The (void) portion means that the method will not return anything back when it finishes executing. If the class was going to return an integer, this would be changed to (int) and the same for any other data type. Finally, we finalize the method declaration with a semicolon.

Implementation
1. 2. 3. 4. 5. 6. 7. 8. 9. #import "Car.h" @implementation Car -(void) addGas { // code goes here to add gas } @end

The implementation in this case contains the method to add gas to the tank. We also import Car.h, which is the interface file. Where our addGas method sits, we could add many more methods, but todays scope is to simply get you to understand how classes work rather than make a fully-fledged class.

Next Time
Next time well be looking more in depth at methods and at using variables with methods (as well as the basics of managing variables in Objective-C). This tutorial wasnt too long as its often a bit confusing for new developers as to why we separate classes in to more than one file. If youre feeling at all confused then please re-read the above or ask questions in the comments section below. Classes will be a constant reoccurrence in this series and its important you understand how they work.

Challenge
Seeing as this part of the series was fairly theoretical, theres not too much you can do to practice. However, I do recommend this week that you sign up for Apples developer website as its an invaluable reference. Once youve done that, have a snoop around some of their downloadable classes and download a few simple ones. You dont need to understand all of the code, just look at how the classes are formed and separated across files.

Welcome to part three of this series -I hope youre enjoying it! Last week we looked at how we separate classes in to separate files (interface and implementation), this week were going to look at classes again, but a little bit more in depth. Well also take a peak at inheritance and how it works, along with variable scope. So far, we have had some great feedback via email, twitter and comments. Its great to see so many people are interested in this subject and its even better to see that so many of you are trying it out for yourself and asking some great questions. Keep it up!

In Review: Classes & Objects


Lets review what we have learned about classes in this series so far. If you dont know any of this, feel free to skim back to the last tutorial to re-cap. Ok, so, what are classes? A class is a collection of encapsulated data and custom methods. A class may hold many different kinds of data, and the class methods usually (but not always) perform action related to that data. In Objective-C, a class is usually composed of two files: an interface file and an implementation file. The interface file uses the .h file extension by convention and is where the person using the class can quickly find the methods and data members available to the class. The implementation file uses the .m file extension by convention and is where the majority of the code resides because it contains the actual implementation of all the functions declared in the interface. So, what makes a class different from an object? What is an object? An object is an instance of a class. Think back to our example with the car in the last part of the series. Where car is the class, then myCar, dansCar, and yourCar would all be objects because they are instances of the car class.

Classes from Apple (and some history)


Before we carry on, Id like to share a few (of many) common classes youll be using a lot that are provided by Apple, but first a quick history lesson. Many classes Apple provides are prepended by the abbreviation NS, which stands for NextStep. When Steve Jobs left Apple, he founded NeXT, creating workstation computers that ran on its operating system. The object orientated programming language used on those machines was called NeXTSTEP, which is where we get the NS from. When Apple acquired (another history lesson in itself) NeXTSTEP, they decided to base Mac OS X on NeXTSTEP. Here are some simple, common classes well see a lot of:

NSString is a string of text that is immutable. NSMutableString is a string of text that is mutable. NSArray is an array of objects that is immutable. NSMutableArray is an array of objects that is mutable. NSNumber holds a numeric value.

Well learn many more later on, but for now the above will come in handy. Youre probably wondering what mutable and immutable means, which is an entirely reasonable question. If an object is immutable that means when we create the object and assign a value then it is static. The value can not be changed. If an object is mutable then it is dynamic, meaning the value can be changed after creation.

Pointers and Initializing


Lets say we want to make a static string of text and log it, how would we go about it? In our code it would look something like this: 1. #import <Foundation/Foundation.h> 2. 3. int main (int argc, const char * argv[]) { 4. 5. NSString *testString; 6. testString = [[NSString alloc] init]; 7. testString = @"Here's a test string in testString!"; 8. NSLog(@"testString: %@", testString); 9. 10. return 0; 11. 12. } I created this file in XCode by going to File > New Project > Mac OS X > Application > Command Line Tool > Type: Foundation (quite a journey!) and editing the implementation (extension: .m) file in the project. There are quite a few things here that are new, so lets examine the above piece by piece. First of all, we import the foundation library (this is because we set type to Foundation in the new project window before). 1. int main (int argc, const char * argv[]) { This declares the initial function that will be called when our program begins execution. The two parameters separated by a comma are for passing arguments to our application. For now, dont worry about these as we wont be needing them right now. 1. NSString *testString; testString = [[NSString alloc] init]; We now create a pointer to an NSString object called testString. Once the first line of this is finished, no string exists yet, only a pointer to a string that we have not yet created. On the next line, we create the string our pointer points to. We could have alternatively written the last line like this; 1. testString = [NSString alloc]; 2. [testString init];

This may seem a little confusing at first. In the first version, we have nested the statements within brackets on the same line, whereas in the second we have separated the statements into two lines. The method init initializes all the instance variables in the class. 1. testString = @"Here's a test string in testString!"; This line is pretty self explanatory, the reason we prepend the quotes with an @ sign is to tell the compiler that the following text is an NSString. NSLog(@testString: %@, testString); Here we log some information to console. XCode has a debugger built in that you can find under the Run menu. It is very useful when developing an application to log when events are happening and the values of certain variables it can help when troubleshooting your application and debugging problems. This method works like printf (remember from the first week?) where we supply a string of text with a replacement character (%@ means an Objective-C object).

Finally we return 0, which we know just tells the operating system that the application ended with no problems.

Inheritance
Remember when we made our NSString earlier, we used the init method? Well NSMutableString, NSArray and in fact, every single NS class, also uses init. Seems a lot of wasted code to put the init method in each class, right? It would be, thats why init is usually only implemented once, in the root class known as NSObject. Because classes inherit from each other, a class that is created as a child of another, parent class will automatically gain access to the parent class methods.

Lets take NSMutableString for example. NSMutableString has NSString for a parent (making it a child), meaning it inherits from NSString. Meanwhile. NSString has NSObject as a parent, so it inherits from NSObject.

So for example, NSObject has a method called init, so each subclass has this method implemented which is called a class method. As a matter of fact, the init method in NSObject doesnt actually do anything it simply returns self. The reason for this is that methods can be overwritten. So the NSArray class may override the init that it inherits to add functionality to it such as making sure memory is available or preparing any instance variables it may need. As demonstrated, this is useful because it means that in addition to inheriting from classes we can also extend classes. When we extend a class, we take an existing class and add additional functionality to what is already available. This means you could create your own version of NSString with additional methods, such as a method to fill the string with random text or perform some sort of character encoding.

Summary
At this point, the fundamentals of how classes work should be clear. To test your comprehension, see if you can answer the following questions in your mind:

What is the difference between a class and an object? Why do we use classes? Why is inheritance useful?

Since classes are such an important part of Objective-C, its important to really feel comfortable working with them. Last week we started looking at classes and this week we have gone into more depth. Next week, you may be glad to hear, were going to move away from the theoretical side and start working on our own simple class or two to perform simple tasks.

Homework

Since we have mainly done theory so far, your homework this week is to surf Apples developer website (you should have done this last week) and look at some of the classes available. If you dont know where to start, start with something such as NSString. Youll become more comfortable with the details of the parent class, the methods, and so on. This will be important later on when youre using classes outside of this series and you want to know what methods they inherit or use.

Next Time
Well get more practical next week with some class coding. Classes really are central to Objective-C, so its mega important that you come to grips with them and the goal of this series is to really ensure that you do! As usual, if you have any questions or comments, you can reach me by dropping a comment or email. If youd like to get in touch with me personally and get a quick answer, send me a tweet!

Welcome to part four of this series on Objective-C. So far, weve looked a lot at theory and the principles and functionality of the language to get a good idea of how it works. Today, we

will be making a simple class similar to the car example we looked at in previous parts of this series. Our class will take the details of a car, allowing us to get and set the values held. After todays example you should be able to create your own classes in Xcode and toy around with them. So far, we have had some great feedback via email, twitter and comments. Its great to see so many people are interested in this subject and its even better to see that so many of you are trying it out for yourself and asking some great questions. Keep it up!

Getting Started
Start by firing up Xcode and creating a new project. Under the Mac OS X separator, click Application, then click Command Line Tool. Finally, change the drop down box to set the type to Foundation.

Save the project as whatever you want, I called mine CarApp. Once the project window appears, we need to create a new class. Hit Command-N (or File > New File), navigate to Cocoa Class under Mac OS X and select Objective-C class. Make sure Subclass of is set to NSObject and press Next. Name your class SimpleCar and ensure that a .h file will be created, then save it.

Our class now exists, but it does nothing. Lets change that by giving it some code. Remember that in Objective-C we split our code into two parts: interface and implementation. It makes logical sense to work on the interface first, so thats where well start.

Coding the Interface


Open up the SimpleCar.h file and in its current state it should look like this (Ive omitted the comment header from below) 1. 2. 3. 4. 5. 6. 7. #import <Cocoa/Cocoa.h> @interface SimpleCar : NSObject { } @end

First of all, were including Cocoa.h, which gives us access to such things as NSString, NSMutableString, etc. Then, we create our class (SimpleCar) as a subclass of NSObject. Now we need to decide on what information our class needs to store. Since were using a car as our example we need to store car-related information, such as:

Make Model VIN

Theres a lot more we could go into, but for now that will do. For each of these properties, we need to store them in a variable suited for that type of data. Make and model will be a range of characters (such as text, number and possibly punctuation) so it makes sense to use a string. The VIN (Vehicle Identification Number) will only be a number so thats what well use. Our code now looks like this (header omitted): 1. @interface SimpleCar : NSObject { 2. NSString* make; 3. NSString* model; 4. NSNumber* vin; 5. } 6. 7. @end We previously said that in order to get or set data from a class, a method should be used. So to set the variables, we need to add methods. To do this, well make four: one will set the make, one the model, one the VIN, and a final method will set both make AND model (just to show you how to use multiple arguments).

1. @interface SimpleCar : NSObject { 2. NSString* make; 3. NSString* model; 4. NSNumber* vin; 5. } 6. 7. // set methods 8. - (void) setVin: (NSNumber*)newVin; 9. - (void) setMake: (NSString*)newMake; 10. - (void) setModel: (NSString*)setModel; 11. 12. // convenience method 13. - (void) setMake: (NSString*)newMake 14. andModel: (NSString*)newModel; 15. 16. @end We declare methods after the curly bracket and before @end. By placing a dash (minus sign) before the method, we tell the compiler were about to declare an instance method. An instance method is a method executed on our instance. Conversely, a plus sign indicates that the method being invoked is a class method that does not need an individual object instance to execute -more on this later. Our first method returns void, is called setVin and takes an NSNumber as an argument. Our second method is similar, it returns void, is call setMake, and takes an NSString as an argument. The third is the same, with a different name. Our final method also returns void but takes two parameters: newMake and newModel, both of which should be NSString. The naming used in this method is similar to how most Objective-C methods are named: in plain English. So when you read the method allowed its obvious that the method will Set make and model. Its important to remember that the method name in this case is setMake:andModel: all the argument titles are included in the method name. An important note is that we use (void) because our methods do not need to return anything. Since all they are doing is setting data and do not need to return anything back (such as a success message) we simply use void. Next, we will add the methods we will use to get the values. Although we call our methods get and set methods, we only usually use set in the title and omit get. How you name your methods is ultimately up to you, but dropping get is common and helps avoid confusion. Our new set of methods looks like this:

1. // set methods 2. - (void) setVin: (NSNumber*)newVin; 3. - (void) setMake: (NSString*)newMake; 4. - (void) setModel: (NSString*)newModel; 5. 6. // convenience method 7. - (void) setMake: (NSString*)newMake 8. andModel: (NSString*)newModel; 9. 10. // get methods 11. - (NSString*) make; 12. - (NSString*) model; 13. - (NSNumber*) vin; Notice that the get methods use the same names as the variables in the class. This will make it simple when we fetch the variables. It will be as if were accessing the variables directly, essentially making the get methods appear transparent.

Coding the Implementation


So now that the interface is in place and we know what the class will do, we need to implement our methods. Looking back, we have four methods we need to implement: setVin, setMake, setModel and setMake:andModel. Before we move files, copy the method declarations to your clipboard (Cmd+C). Now close SimpleCar.h and fire up SimpleCar.m in the editor, pasting the method declarations in between the @implementation and @end, like so: 1. @implementation SimpleCar 2. 3. // set methods 4. - (void) setVin: (NSNumber*)newVin; 5. - (void) setMake: (NSString*)newMake; 6. - (void) setModel: (NSString*)newModel; 7. 8. // convenience method 9. - (void) setMake: (NSString*)newMake 10. andModel: (NSString*)newModel; 11. 12. // get methods 13. - (NSString*) make; 14. - (NSString*) model; 15. - (NSNumber*) vin; 16. 17. @end Obviously this isnt right, so what we need to do is swap the semi-colons for curly brackets where the inner workings of the method will go, like this:

1. @implementation SimpleCar 2. 3. // set methods 4. - (void) setVin: (NSNumber*)newVin { 5. 6. } 7. 8. - (void) setMake: (NSString*)newMake { 9. 10. } 11. 12. - (void) setModel: (NSString*)newModel { 13. 14. } 15. 16. - (void) setMake: (NSString*)newMake 17. andModel: (NSString*)newModel { 18. 19. } 20. 21. // get methods 22. - (NSString*) make { 23. 24. } 25. 26. - (NSString*) model { 27. 28. } 29. 30. - (NSNumber*) vin { 31. 32. } 33. 34. @end Now we need to give our methods some code. Lets start with the getter methods as theyre straightforward enough. For each getter method, all we need to do is make sure that the function returns what it is intended to return. For this reason, our getter methods look like this:

1. 2. 3. 4. 5. 6. 7. 8.

- (NSString*) make { return make; } - (NSString*) model { return model; }

9. - (NSNumber*) vin { 10. return vin; 11. } Remember: the methods are returning the variables we defined in the interface file. Dont get confused between the method names and the variable names. Thats pretty straightforward, when we call make (for example), then make returns the pointer to an NSString in this case to the make variable. The same happens for model and vin (except of course vin returns a number). Now for the setter methods, first well look at the code and then well go through it afterwards. Our setter methods look like this: 1. // set methods 2. - (void) setVin: (NSNumber*)newVin { 3. 4. [vin release]; 5. vin = [[NSNumber alloc] init]; 6. vin = newVin; 7. 8. } 9. 10. - (void) setMake: (NSString*)newMake { 11. 12. [make release]; 13. make = [[NSString alloc] initWithString:newMake]; 14. 15. } 16. 17. - (void) setModel: (NSString*)newModel { 18. 19. [model release]; 20. model = [[NSString alloc] initWithString:newModel]; 21. 22. } 23. 24. // convenience method 25. - (void) setMake: (NSString*)newMake 26. andModel: (NSString*)newModel { 27. 28. // Reuse our methods from earlier 29. [self setMake:newMake]; 30. [self setModel:newModel]; 31. 32. } The set methods are a bit trickier than our get methods. We want to alloc the values that are passed into each method so that they are owned by the class. We first release these variables in case they are already allocd. If they are not allocd, then they are nil, and nil objects ignore

messages passed to them. We will cover these issues more when we discuss memory management. Because we actually allocated memory for our objects in the setter methods, we need to be sure we release them when the object is released from memory. To do this, we need to add a custom dealloc method, like so: 1. -(void) dealloc 2. { 3. [vin release]; 4. [make release]; 5. [model release]; 6. [super dealloc]; 7. }

Testing the Class


Congratulations! If you followed everything above then you should now have a working class (if not, download the source files available with this article). So, lets test it out. Open up the main file of your project (mine is called CarApp.m) which by default should look something like this: 1. #import <Foundation/Foundation.h> 2. 3. int main (int argc, const char * argv[]) { 4. 5. NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; 6. 7. // Insert custom code here... 8. NSLog(@"Hello, World!"); 9. 10. [pool drain]; 11. return 0; 12. } Delete the comment and NSLog line as we wont be needing them right now. In order to begin using our class, we need to pull it into the program. Underneath the original #import line add the following line: 1. #import "SimpleCar.h" Our class is now available for use, but we need to create an instance of it in order to test it out. Heres the code used in total:

1. #import <Foundation/Foundation.h> 2. #import "SimpleCar.h" 3. 4. int main (int argc, const char * argv[]) { 5. 6. NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; 7. 8. SimpleCar *myCar = [[SimpleCar alloc] init]; 9. 10. NSNumber *newVin = [NSNumber numberWithInt:123]; 11. 12. [myCar setVin:newVin]; 13. [myCar setMake:@"Honda" andModel:@"Civic"]; 14. 15. NSLog(@"The car is: %@ %@", [myCar make], [myCar model]); 16. NSLog(@"The vin is: %@", [myCar vin]); 17. 18. [myCar release]; 19. 20. [pool drain]; 21. 22. return 0; 23. } First of all we create a pointer to an instance of SimpleCar called myCar. Next we use alloc and init these will be discussed later on down the line. Next, since we need to pass an NSNumber to the setVin method, we make one here. Again we create a pointer to an NSNumber instance called newVin and we initiate it with the integer value of 123. The constant 123 is an integer, which is why we use numberWithInt. Next, we invoke our methods, first of all we put who should receive the message (myCar) and then we use the method setVin. After the colon is the value we are supplying to the method which is the NSNumber we created before. Next we do the same but call the setMake method with two parameters. The reason these parameters are preceded by an @ sign is to tell the compiler that the following is a string. Finally, we release myCar as we are done with it more on this later in the series under memory management. Our class is now working, and in order to see the proof, we added some NSLog statements to print the values to the console. If you open up the console (Run > Console) and then build and run your app, you should see output similar to this:

Property and Synthesize


If you look at the code above, a lot of it seems quite pointless and excessive. For example, in our getter methods all we are doing is returning an instance variable but this takes up three lines of code to do something simple. Also, in our setter methods, we are just setting instance variables essentially all of our methods, except our method that takes two arguments, seem bloated and in the way. Objective-C solves this with @property and @synthesize, which replace our accessor methods and make for much neater coding. This is what our new interface file looks like using properties: 1. #import <cocoa cocoa.h=""> 2. 3. @interface SimpleCar : NSObject { 4. NSString* make; 5. NSString* model; 6. NSNumber* vin; 7. } 8. 9. @property(readwrite, retain) NSString* make; 10. @property(readwrite, retain) NSString* model; 11. @property(readwrite, retain) NSNumber* vin; 12. 13. // convenience method 14. - (void) setMake: (NSString*)newMake 15. andModel: (NSString*)newModel; 16. 17. @end 18. </cocoa> Wow, that really is a lot shorter. So whats happening with the @property declarations? First we tell the compiler we are declaring a property by using @property, then we follow with attributes for this property. The attributes are the read/write status of a property and some memory management. We have used readwrite for all, which means getter and setter methods

are dynamically created for our instance variables (we could of used writeonly or readonly for just one or the other). The reason we use retain will become clear next time when we cover memory management. Before this can work, we need to implement it in our implementation file, we do this using @synthesize. Our new implementation file looks like this: 1. #import "SimpleCar.h" 2. 3. @implementation SimpleCar 4. 5. @synthesize make, model, vin; 6. 7. - (void) setMake: (NSString*)newMake 8. andModel: (NSString*)newModel { 9. 10. [self setMake:newMake]; 11. [self setModel:newModel]; 12. 13. } 14. 15. @end Doesnt that look better? Think of it like this, @property replaces all of the interface method declarations for getters and setters, and @synthesize replaces the actual methods themselves. The getters and setters are now dynamically created and we dont need to waste time creating them unless we need to do something really special.

Wrapping Up
You should now have a firm grip of classes, objects and instances. Sure, youre not creating classes that will change the world yet, but this stuff takes time. Its better to learn by example, so if youre not coding as you go along then be sure to at least download the source files and have a read through (and a compile) to ensure youre 100% on whats going on.

Next Time
Weve mentioned memory management a lot in this tutorial, its a very important subject that needs to be addressed (pun intended), so well dive in to that next time. True, it isnt the most fun subject or the easiest to come to terms with, but its absolutely crucial if you want to become a skilled Objective-C programmer.

Challenge
This weeks challenge may be a little tricky, but well see how you get on. First of all, if you havent copied all the code above, download the source files that are included with this article. The challenge is to add another class to the project, but this time it should be a subclass of SimpleCar (remember, we define the parent class in the interface file). If you can do that, play

around and use the inherited methods and try to add your own for things such as: engine size, doors or height. Remember: if you have any questions or queries, drop a comment below or shoot me a message on Twitter. The only stupid question is the one you didnt ask this series is about learning so feel free to ask away!

Welcome to part five of this series on Objective-C. Today were going to look at memory management, an element of Objective-C (and many other languages) that tends to trip up newer programmers. Most scripting languages (such as PHP) take care of memory managaement automatically, but Objective-C requires that we are careful with our use of memory and manually create and release space for our objects. Its good practice to keep track of how much memory your application is using, so you dont encounter any leaks or hog up the memory on the system. Its even more important on mobile systems such as the iPhone where memory is much more limited than on a desktop machine.

Two Approaches
In Objective-C there are two methods for managing memory, the first if reference counting and the second is garbage collection. You can think of them as manual and automatic, as reference counting is code added by the programmer and garbage collection is the system automatically managing our memory. An important note is that garbage collection does not work on the iPhone, which is why we will not look at how it works. If you should wish to program for the Mac, then its worth looking at Apples documentation to see how garbage collection works.

Reference Counting
So, how do we manage our memory in our apps? First of all, when do we use memory in our code? When you create an instance of a class (an object), memory is allocated and our object can now function correctly. Now one little object might not seem that great of a deal, but when your apps grow in size it quickly becomes an enormous problem. Lets look at an example, say we have some sort of drawing app and each shape the user draws is a separate object. If the user has drawn 100 shapes, then we have 100 objects sat in memory. Now lets say the user starts over and clears the screen, then draws another 100 objects. If we dont manage our memory properly, were going to end up with 200 objects doing nothing more than hogging memory. We counter this by reference counting. When we create a new object and use alloc, our objects have a retain count of 1. If we call retain on that object, the retain count is now 2 and so on. If we release the object, the retain count decrements back to 1. Whilst the retain count is non-zero, our object will stick around, but when the retain count hits zero, the system deallocates our object freeing up the memory.

Syntax
There are various methods you can call that will have some effect on memory management. First of all, when you create an object using a method name that contains alloc, new or copy, you take ownership of that object. This is also true if you use the retain method on an object. Once you release, or autorelease (more on that later) an object, you no longer take ownership of that object or care what happens to it. So, if we alloc an object like so;

1. myCarClass *car = [myCarClass alloc]; We are now responsible for the object car and we must manually release it later (or autorelease it). Its important to note that if you were to try and manually release an object that has been set to autorelease, the application would crash. Since we created our object using alloc, our car object now has a retain count of 1, meaning it will not be deallocated. If were to also retain our object like so; 1. [car retain]; Then our retain count is now 2. So in order to get rid of the object, we need to release twice to set the retain count to 0. Since the retain count is now zero, the object will be deallocated.

Autorelease and Autorelease Pools


When youve created a new XCode project, you may have noticed some code that appears by default which creates an autorelease pool, up until now youve ignored it now were going to see what it does and where to use it. The code youre probably familiar with seeing by now should look like this; 1. NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; 2. 3. [pool drain]; Note: if you refer to older documentation, you may see the last line as release, rather than drain, this is a newer addition to the language but essentially does the same thing. By now you should be able to tell to some extent what the code above is doing; it is creating an instance of NSAutoReleasePool called pool, allocating memory for it and then initiating it using the init method. When we send the autorelease message to an object, that object is then added to the inner most auto release pool (inner-most because pools can be nested within each other more on that later). When the pool is sent the drain message, then all the objects sent the autorelease message are released, essentially autorelease is deferring the release until later. This is useful because many methods that return an object, typically return an autoreleased object, which means we dont have to worry about the retain count of the object we just got given, nor do we have to release it, as it will be done later on.

Nested Autorelease Pools


I spoke briefly before about the ability to nest autoreleased pools, but what use is that to us? Although there are several uses, one of the most common uses is to nest an autorelease pool inside a loop that uses temporary objects. For example, if you have a loop that creates two temporary objects to do whatever it is you wish, if you set those two objects to autorelease, you can use them until the pool is sent the

drain message and not have to worry about manually releasing to deallocate. Apple have a great example of when youd use this kind of nested autorelease pool in their documentation; 1. void main() 2. { 3. NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; 4. 5. NSArray *args = [[NSProcessInfo processInfo] arguments]; 6. 7. for (NSString *fileName in args) { 8. 9. NSAutoreleasePool *loopPool = [[NSAutoreleasePool alloc] init]; 10. 11. NSError *error = nil; 12. NSString *fileContents = [[[NSString alloc] initWithContentsOfFile:fileName 13. encoding:NSUTF8StringEncoding error:&err or] autorelease]; 14. 15. /* Process the string, creating and autoreleasing more objects. */ 16. 17. [loopPool drain]; 18. } 19. 20. /* Do whatever cleanup is needed. */ 21. [pool drain]; 22. 23. exit (EXIT_SUCCESS); 24. } The above example has a bit more than we need, but the structure is there. As you can see, when the application is opened and main is loaded, an autorelease pool called pool is created. Meaning anything autoreleased before the pool is sent the drain message will be assigned to this autorelease pool, unless it is inside an autorelease pool inside this one (sorry if that sounds a little confusing). Inside the loop, another autorelease pool is created called loopPool. This pool is drained inside the loop, so anything autoreleased inside the loop is released before the loop iterates (or ends). The inner autorelease pool has absolutely no effect on the outer autorelease pool, you may nest as many autorelease pools as you need. If we used autorelease in the loop above, but did not have a separate autorelease pool, then all the objects we were creating would not be released until the end of main. So if the loop ran 100 times, we would have 100 objects hogging up memory that have yet to be released bloating our application.

retainCount
Before we wrap up, lets look at something that could help make memory management an easier-to-swallow chapter. So far when weve created objects, weve remembered how many references an object has and so on but weve never seen an actual number. For the purposes

of education, there is a method we can use to see how many references an object has called retainCount. The way we print a retainCount for an object is like so; 1. NSLog(@"retainCount for car: %d", [car retainCount]); retainCount returns an integer, so we use %d to display it in the console. There are rare instances (which we wont go in to) where retainCount can be wrong and as such should not be 100% relied upon programatically. It is implemented for debugging only, so an app should never go live using the retainCount method.

Wrapping Up
Memory management is a subject that many new programmers find difficult, especially programmers who come from languages that take care of it all for you. Weve covered the basics, which should be enough to allow you to find your feet and start incorporating memory management in to your apps. Apple has a fantastic developer documentation library available on their developer website, which I highly recommend you check out if youre unclear on anything we touched on today. Weve tried to keep the tutorial short and laser-focused today to help you understand memory management with no other fluff added. Questions are welcome, as usual.

Challenge
Simply experiment with the console by creating a simple object that contains a few synthesized variables, create a few instances of this class and then check the retain count using the retainCount method. The best way to understand memory management is to fire up XCode and play around with allocs and retains etc, remember that crashes and mistakes arent a brick wall as theyll ultimately help you avoid the mistakes in future.

Next Time
In the next installment well be looking at categories, a great feature available in Objective-C that can save developers a lot of time and make for more simplistic code.

In todays tutorial, you will learn about Categories and how to use them to extend the functionality of Cocoa-Touch classes. This is our final installment in the Learn Objective-C series, so you will also be provided with a quick recap on what weve covered so far and then look at what you can do to further your skills as an Objective-C or iPhone application developer.

Categories
So, what are categories? A lot of Objective-C tutorials and series will overlook categories, which is a shame as theyre such a useful language feature thats amazingly useful. Categories help keep code clean and less cluttered by eliminating the need for unnecessary subclassing. From what weve learned so far, if we had an NSString object that we wanted to add functionality to do something like add a method that would replace all the a characters with a 4 (useless I know, but for example purposes only), then we could subclass NSString and add the method ourselves. We also saw this kind of subclassing when we made our car class, I asked you at the end of that tutorial to make a subclass of car so you could add functionality to the base class. Subclassing is a good approach, and I am in no way telling you to stop subclassing, but, in certain situations, categories provide a better approach to add some extra functionality to a class. Categories allow us to add methods to an existing class, so that all instances of that class in your application gain your functionality. For example, say we have 100 NSString objects in your app, but youd like to make a custom subclass so each NSString has an extra method (reverseString for example). With categories we can simply add the method in a category and all instances will be allowed to use the new method. The syntax is obviously slightly different from subclassing and categories dont allow you to use instance variables. However, it is possible to overwrite a method already in place, but this should be done with caution and only if doing so is really necessary.

Syntax
Categories follow the same syntax layout as a class, as in they have an implementation and an interface. The interface looks like this: 1. @interface ClassNameHere (category) 2. 3. // method declaration(s) 4. 5. @end 6. 7. The implementation looks like this; 8. 9. @implementation ClassNameHere (category) 10. 11. // method implementation(s) 12. 13. @end

Example
Easy, right? So lets look at an example. Were going to make a simple method that will reverse a string. While this method is practically useless; its not what the method is doing thats important. You should already know what the interface will look like, but here it is anyway: 1. @interface NSString (reverse) 2. 3. -(NSString *) reverseString; 4. 5. @end Now to create our implementation: 1. 2. 3. 4. 5. 6. 7. @implementation NSString (reverse) -(NSString *)reverseString { } @end

Next, well need to add some simple code to flip the string around. Since were adding methods to the NSString class, we reference the string using self. Now in order to reverse the string well need a new, temporary string object to hold the reversed string. The way we will reverse the string is to simply loop through the existing string in reverse, each time we find a new character well add it to the reversed string object. The code for this is: 1. 2. 3. 4. 5. 6. 7. int length = [self length]; NSMutableString *reversedString; reversedString = [[NSMutableString alloc] initWithCapacity: length];

while (length > 0) { [reversedString appendString:[NSString stringWithFormat:@"%C", [self character AtIndex:--length]]]; 8. } 9. 10. return [reversedString autorelease]; This method is fairly simple, were looping through once for each character in the string. We append the current character using stringWithFormat and the character (C) identifier. When we call length we not only return the length integer, we also subtract from it too, which is how our loop moves along the string. If all has gone well then all NSStrings already in our project should adhere to our new category. Now you can see why categories are so useful!

Using Our Example


Ok, now all of our NSString objects should have our reverseString method. Just to recap, our code should look like this:

1. @interface NSString (reverse) 2. 3. -(NSString *) reverseString; 4. 5. @end 6. 7. @implementation NSString (reverse) 8. 9. -(NSString *)reverseString { 10. int length = [self length]; 11. NSMutableString *reversedString; 12. 13. reversedString = [[NSMutableString alloc] initWithCapacity: length]; 14. 15. while (length > 0) { 16. [reversedString appendString:[NSString stringWithFormat:@"%C", [self charact erAtIndex:--length]]]; 17. } 18. 19. return [reversedString autorelease]; 20. } 21. 22. @end Each block of code (interface and implementation) should be in their own respective files by convention. However, we name categories a little differently. The two files we have created are named: NSString+reverse.h (interface) and NSString+reverse.m (implementation). This is a typical naming convention following the pattern of the name of the class we are adding a category to, a plus sign, and the name of our category. Before we continue, remember that we still need to include our header file into the main project. So now our code should look something like this: 1. NSString* testString = @"Just a test"; 2. 3. [testString reverseString]; 4. 5. NSLog(@"Reversed: '%@'", testString); If all went according to plan, then the Console should log a reversed version of Just a test!

If all doesnt go according to plan, check to be sure youve copied the code for reverseString properly and make sure youre including the header (*.h) file for the category in your main code file. As you can see, categories really are quite useful (especially with strings). They have a wide range of uses in any project, a common one I use is validation. This way I can keep all of my validation in one place and dont have to use any complicated subclasses.

Wrapping Up The Series


Not only is this the end of todays tutorial, this is the end of the series on the fundamentals of Objective-C. Over the last several tutorials weve covered the following topics:

Fundamentals of Programming Fundamentals of OOP Classes and Subclasses Memory Management Good Practice Some Standard Naming Conventions

I hope youve enjoyed this series, and if youve only read one or two of the tutorials so far, then I encourage you to start at day 1 and read a tutorial a day. By the end of the series you should be confident enough to start writing your own code in just under a week! If you have any questions about the series or examples shown, or if you would like an additional tutorial on another area of Objective-C programming, feel free to leave a comment below. If you have any questions on Objective-C itself, a project that youre working on, or just some technical advice, dont hesitate to drop me a mention or direct message on Twitter or visit my website and find your way to the contact form!

Challenge
Now that were finished, the challenges are endless. I highly suggest you put pen to paper and decide on a first app to build from start to scratch. Come up with an idea and a design, then apply all the principles you have learned from this series and let us know what you come up with! Thanks for reading!

Potrebbero piacerti anche