Get $500+ of the best After Effects files, video templates and music for only $20!
Learn Objective-C: Day 4
basix

Learn Objective-C: Day 4

Tutorial Details
  • Difficulty: Beginner
  • Technology: Objective-C
  • Completion Time: 20 - 45 Minutes
This entry is part 4 of 6 in the series Learn Objective-C

Welcome to part four of this series on Objective-C. So far, we’ve 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 today’s 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. Itʼs great to see so many people are interested in this subject and itʼs 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.

Xcode New Project

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. Let’s 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 that’s where we’ll start.

Coding the Interface

Open up the SimpleCar.h file and in its current state it should look like this (I’ve omitted the comment header from below)

#import <Cocoa/Cocoa.h>

@interface SimpleCar : NSObject {

}

@end

First of all, we’re 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 we’re using a car as our example we need to store car-related information, such as:

  • Make
  • Model
  • VIN

There’s 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 that’s what we’ll use. Our code now looks like this (header omitted):

@interface SimpleCar : NSObject {
	NSString* make;
	NSString* model;
	NSNumber* vin;
}

@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, we’ll 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).

@interface SimpleCar : NSObject {
	NSString* make;
	NSString* model;
	NSNumber* vin;
}

// set methods
- (void) setVin:   (NSNumber*)newVin;
- (void) setMake:  (NSString*)newMake;
- (void) setModel: (NSString*)setModel;

// convenience method
- (void) setMake: (NSString*)newMake
        andModel: (NSString*)newModel;

@end

We declare methods after the curly bracket and before @end. By placing a dash (minus sign) before the method, we tell the compiler we’re 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 it’s obvious that the method will “Set make and model.” It’s 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:

// set methods
- (void) setVin:   (NSNumber*)newVin;
- (void) setMake:  (NSString*)newMake;
- (void) setModel: (NSString*)newModel;

// convenience method
- (void) setMake: (NSString*)newMake
        andModel: (NSString*)newModel;

// get methods
- (NSString*) make;
- (NSString*) model;
- (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 we’re 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:

@implementation SimpleCar

// set methods
- (void) setVin:   (NSNumber*)newVin;
- (void) setMake:  (NSString*)newMake;
- (void) setModel: (NSString*)newModel;

// convenience method
- (void) setMake: (NSString*)newMake
        andModel: (NSString*)newModel;

// get methods
- (NSString*) make;
- (NSString*) model;
- (NSNumber*) vin;

@end

Obviously this isn’t 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:

@implementation SimpleCar

// set methods
- (void) setVin: (NSNumber*)newVin {

}

- (void) setMake: (NSString*)newMake {

}

- (void) setModel: (NSString*)newModel {

}

- (void) setMake: (NSString*)newMake
        andModel: (NSString*)newModel {

}

// get methods
- (NSString*) make {

}

- (NSString*) model {

}

- (NSNumber*) vin {

}

@end

Now we need to give our methods some code. Let’s start with the getter methods as they’re 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:

- (NSString*) make {
    return make;
}

- (NSString*) model {
    return model;
}

- (NSNumber*) vin {
    return vin;
}

Remember: the methods are returning the variables we defined in the interface file. Don’t get confused between the method names and the variable names.

That’s 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 we’ll look at the code and then we’ll go through it afterwards. Our setter methods look like this:

// set methods
- (void) setVin: (NSNumber*)newVin {

    [vin release];
    vin = [[NSNumber alloc] init];
    vin = newVin;

}

- (void) setMake: (NSString*)newMake {

    [make release];
    make = [[NSString alloc] initWithString:newMake];

}

- (void) setModel: (NSString*)newModel {

    [model release];
    model = [[NSString alloc] initWithString:newModel];

}

// convenience method
- (void) setMake: (NSString*)newMake
        andModel: (NSString*)newModel {

    // Reuse our methods from earlier
    [self setMake:newMake];
    [self setModel:newModel];

}

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 alloc’d. If they are not alloc’d, 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:

-(void) dealloc
{
    [vin release];
    [make release];
    [model release];
    [super dealloc];
}

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, let’s test it out.

Open up the main file of your project (mine is called CarApp.m) which by default should look something like this:

#import <Foundation/Foundation.h>

int main (int argc, const char * argv[]) {

    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

    // Insert custom code here...
    NSLog(@"Hello, World!");

    [pool drain];
    return 0;
}

Delete the comment and NSLog line as we won’t 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:

#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. Here’s the code used in total:

#import <Foundation/Foundation.h>
#import "SimpleCar.h"

int main (int argc, const char * argv[]) {

  NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

    SimpleCar *myCar = [[SimpleCar alloc] init];

    NSNumber *newVin = [NSNumber numberWithInt:123];

    [myCar setVin:newVin];
    [myCar setMake:@"Honda" andModel:@"Civic"];

    NSLog(@"The car is: %@ %@", [myCar make], [myCar model]);
    NSLog(@"The vin is: %@", [myCar vin]);

    [myCar release];

  [pool drain];

  return 0;
}

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:

Debugger

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:

#import 

@interface SimpleCar : NSObject {
	NSString* make;
	NSString* model;
	NSNumber* vin;
}

@property(readwrite, retain) NSString* make;
@property(readwrite, retain) NSString* model;
@property(readwrite, retain) NSNumber* vin;

// convenience method
- (void) setMake: (NSString*)newMake
        andModel: (NSString*)newModel;

@end

Wow, that really is a lot shorter. So what’s 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:

#import "SimpleCar.h"

@implementation SimpleCar

@synthesize make, model, vin;

- (void) setMake: (NSString*)newMake
        andModel: (NSString*)newModel {

    [self setMake:newMake];
    [self setModel:newModel];

}

@end

Doesn’t 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 don’t 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, you’re not creating classes that will change the world yet, but this stuff takes time. It’s better to learn by example, so if you’re 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 you’re 100% on what’s going on.

Next Time

We’ve mentioned memory management a lot in this tutorial, it’s a very important subject that needs to be addressed (pun intended), so we’ll dive in to that next time. True, it isn’t the most fun subject or the easiest to come to terms with, but it’s absolutely crucial if you want to become a skilled Objective-C programmer.

Challenge

This week’s challenge may be a little tricky, but we’ll see how you get on. First of all, if you haven’t 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 didn’t ask – this series is about learning so feel free to ask away!

Series Navigation«Learn Objective-C: Day 3Learn Objective-C: Day 5»

Add Comment

Discussion 71 Comments

  1. Matt Vickers says:

    Great explination as always.

    I’ve been playing around with obj-c for a while and this is one of the easier examples to follow that I’ve come across!

    Get em coming.

  2. Ross Hughes says:

    Errata:

    I think the code to display the Vin is incorrect when I was using:

    NSLog(@”The vin is: %d”, [myCar vin]);

    The number being displayed was something along the lines of 110000

    Yet when I changed it to %@ the number displayed was the correct integer of 123.

  3. I’ve done several simple apps now out of my my Beginning iPhone 3 Development by Dave Mark book, and have always wondered, what’s the point of putting the asterisk on the right side? Like this:

    (UiTableView *)tableView

    Veruses putting it like *list?

    • Greg says:

      The asterisk is for declaring any other properties of the UITableView. Most of the time you won’t do this unless you want to customize its attributes.

    • Stop spamming the comments. You basically wrote the same thing on each tutorial page. So I bet that book ain’t that good, if it’s not spread by other people.

  4. Eric L says:

    In your setter methods, you have to test if vin and newVin does not point to the same object, otherwise you could release it before retain it ! You could write something like that :
    - (void) setVin: (NSNumber*)newVin {
    if (vin == newVin)
    {
    return;
    }
    NSNumber *oldValue = vin;
    vin = [newVin retain];
    [oldValue release];
    }

    NSString have a special behavior, it’s better to copy it rather than retain it and write something like that :
    - (void)setModel:(NSString *)newModel
    {
    if (model == newModel)
    {
    return;
    }
    NSString *oldValue = model;
    model = [newModel copy];
    [oldValue release];
    }

    and for your property :
    @property(readwrite, copy) NSString* model;

    you can find more explanations on this blog :
    http://cocoawithlove.com/2010/06/assign-retain-copy-pitfalls-in-obj-c.html

  5. pranav says:

    hi dan…

    I am following your tutorial regurarly and its been really helpful and has good clarity about each and every single concept….good work….

  6. Niklas says:

    This series is just getting better and better. Thanks for your time and effort in making these mate!

  7. Klas says:

    Great series!

    I’m new to pointers so If you (or anyone else) could clarify, in the main method, how come you release myCar and not newVin? Will the address space newVin is pointing to be released automatically when myCar is released because the local variable “vin” is referencing the same address space?

    Thanks

  8. Ben says:

    Really enjoying these. Look forward to the next one. Thanks.

  9. Jacob Tyo says:

    When’s the next one coming? :/

  10. Same here, i’d like to see the next some time soon. I’d also like to see pointers and memory management being explained a bit more thoroughly.

  11. Rahman Sattaur says:

    I just started with the lessons and am new to objective-c. In the interface and implementation files for lesson 4, you used the @property and @ synthesize features to replace ‘getters’ and ‘setters’ for everything except the following:

    # // convenience method
    # – (void) setMake: (NSString*)newMake
    # andModel: (NSString*)newModel;

    I don’t understand why the same feature could not be used here. Am I misunderstanding something?
    I love the tutorials so far. Thank you for providing a means for novices like myself to get to grips with objective-c.

  12. Julio says:

    When I run this code, it successfully compiles, but on the Console window I get these lines:

    Program received signal: “EXC_BAD_ACCESS”.
    sharedlibrary apply-load-rules all

    and I have to stop it manually then. Where may I went wrong here?

    • Tony says:

      Hi Julio,
      I got the same message, with ‘segmentation fault’ in the console, and looking it up in the documentation, it says it was caused by over releasing.
      So I commented out the Auto release stuff in main, didn’t work as this caused other messages, then I tried commenting out the [super dealloc] in SimpleCar.m, and it worked, program exited normally. But I got one warning in Xcode: possibly missing a [super dealloc] call.

      Great tutorial btw
      Tony

      • Alec Peden says:

        Remove the following fix it for me:

        - (void) dealloc
        {
        [vin release];
        [make release];
        [model release];
        [super dealloc];
        }

    • kevin says:

      I think its because we’re releasing in our dealloc method a variable that we created to be autorelease, this fixed it for me, but I how no idea if it creates memory leaks or whatever, but don’t take me to be a final authority on this, I’m just a beginner too:

      // this is an autorelease type of allocation (you can tell because it doesnt have alloc)
      NSNumber *newVin = [NSNumber numberWithInt:123];

      // replace with this, note it calls a different method, because the above method is a class method
      NSNumber *newVin = [[NSNumber alloc] initWithInt:123];

  13. Michael Schroeder says:

    I’ve read all the days up until this point, and I’ve understood it pretty well, but I am very confused now for some reason. I’m somewhat caught up in the use of the * and pointers, and also the alloc and init. I’m not sure why I’m confused, but I definitely don’t understand this lesson very well at all.

  14. Eli says:

    After you change the code to @property and @synthesize, how can the code still run with the setVin method in the main code ( [myCar setVin:newVin]; ) when it seems not to be defined anywhere else (ie it’s not in the .m or .h code)?

    • It’s created automatically by the synthesize function. What it basically do is uppercases the name of the variable, and ads the set in front of it.

      So if the variable is color, setColor will be created.

  15. Aline says:

    I just found your tutorial series yesterday, and as I do have some pascal, c and c++ background I can easily follow and due to your great way to explain things, I also got the feeling I might understand oC someday.
    So today I did the 4. part of your tutorials, I typed the code myself, did some mistakes, compiled, corrected them and so on. When I added the code to main.m, I suddenly got more than 10.000 Errormessages (really.. 11.470) all building ob on an expected “(” in SimpleCar.m in whats line 21 in your code. I checked the .m, I checked the .h, I have no clue.. I also added the NSAutoreleasePool – line, which wasn’t automatically generated. Even more errors that the NSAutoreleasePool wasn’t declared..
    I downloaded your code, copy pasted everything in my project, but it still didn’t run. Your original project works though, although I don’t get any output window.

    Sorry for any foolish beginners mistakes, but I just don’t know what’s wrong..

  16. Gustav S says:

    Hi, on the last code snippet in section “Testing the Class”, why are you only releasing myCar and not newVin. Don’t both of them allocate memory that have to be released?

    Or does this: [NSNumber numberWithInt:123] not allocate any memory (to be released) ?

    //Gustav

    • Peter Nicholls says:

      Now this I do know :D

      you release (or autorelease as well) only what you have obtained by new; alloc, eg: SimpleCar *myCar = [[SimpleCar alloc] init]; or copy.

      • Peter Nicholls says:

        so (if I’m following this correctly):

        ‘myCar’ is the objected / class instance allocated or created from the class ‘SimpleCar’. We create the object, therefore we have to release it.

        The other variables are instance variables in the ‘SimpleCar’ class, and the class is responsible for creating and releasing these in its implementation. We don’t CREATE the ‘vin’ instance variable, we are merely passing it along to the instance of the class, which is ‘myCar’.

        If my reading of this is incorrect, please correct me, I’ve only been learning all this since Jan 1, 2011, coming from html and php background!

  17. Peter Nicholls says:

    Hi there, thanks for this, im doing as many tutroials to really drum this in as poss.

    but one thing vexes me:

    NSString* string; vs. NSString *string;

    what is the difference?

    Thank you so much :)

    • Peter Nicholls says:

      also why

      newVine
      new Make

      BUT then setModel ???? its little things like this that throw, coz i just want to know !!!

      Thank you again :D

      • Bill Jackson says:

        I think the “setModel” when it is used as a variable is a mistake in the tutorial, when I compiled and ran (typed the stuff in my self to get used to the tools) this was one of the errors. changing that to newModel got me over that hump.

        As someone who has never really gotten into object-oriented coding (my coding days are dated back to assembler, Pascal and a little straight C) this has been helpful so far.

    • Endoze says:

      There is actually no difference at all between NSString* string vs NSString *string. It is the programmer’s preference. If I were you, I would pick one and stick with it. Personally I use ClassName* identifier because it helps remind me that I am working with a pointer to a specific type of Class and that the asterisk is not part of the identifier.

  18. vishnu says:

    where does this code go

    -(void) dealloc
    {
    [vin release];
    [make release];
    [model release];
    [super dealloc];
    }

    you don’t say whether it goes in SimpleCar.h or SimpleCar.m….

    in your src code files (your download) this code is nowhere to be found… (it’s not in SimpleCar.h or SimpleCar.m..)

    thank you..

  19. Endoze says:

    I wanted to comment on your setter methods and how you implemented them. I don’t believe that is the best practice for setting instance variables. I think what you should do instead is something like this:

    - (void) setModel: (NSString*)newModel {

    [model autorelease];
    model = [newModel retain];

    }

    }

    The reason I suggest this is simply because by releasing the value of model before you assign a new value to it can be a bit hazardous. I think using autorelease is a bit safer because it says “release at a later time” which translates to at least the end of the current function. I’m also not sure about creating a whole new variable with alloc inside of a setter method. This can cause problems for someone else using your classes because they wouldn’t be aware of the new variable created inside of your setter method and wouldn’t know to release it later. I think your current implementation would cause a memory leak.

  20. Dave says:

    Hi there,

    I just started following your guide and I have made it this far. My only issue is trying the challenge. I have made a class which is a subclass of SimpleCar.h, but I have come across a problem. The class I have created is to define the car color. For my class, CarColor.h, I have the following code:
    //
    // CarColor.h
    // CarApp
    //
    // Created by David on 3/12/11.
    // Copyright 2011 __MyCompanyName__. All rights reserved.
    //

    #import
    #import “SimpleCar.h”
    //Above we imported the SimpleCar class so that we can use it in this subclass

    @interface CarColor : SimpleCar {
    //Here we create the string which we call color
    NSString* color;

    }

    //Now we will give color a property
    @property(readonly, retain) NSString* color;

    @end

    and for CarColor.m I have this code

    //
    // CarColor.m
    // CarApp
    //
    // Created by David on 3/12/11.
    // Copyright 2011 __MyCompanyName__. All rights reserved.
    //

    #import “CarColor.h”

    @implementation CarColor

    @synthesize color;

    - (void) setColor: (NSString *)newColor{

    //Reuse our methods from earlier
    [self setColor:newColor];

    }

    - (void)dealloc
    {
    [color release];
    [super dealloc];
    }

    @end

    My issue becomes when I try and add this to main.m, it won’t execute properly. Here is my code for main.m
    //
    // main.m
    // CarApp
    //
    // Created by David on 3/12/11.
    // Copyright 2011 __MyCompanyName__. All rights reserved.
    //

    #import
    #import “SimpleCar.h”
    #import “CarColor.h”

    int main (int argc, const char * argv[])
    {

    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

    SimpleCar *myCar = [[SimpleCar alloc] init];

    NSNumber *newVin = [NSNumber numberWithInt:123];

    [myCar setVin:newVin];
    [myCar setMake:@"Honda" andModel:@"Civic"];
    [myCar setColor:@"Blue"];

    NSLog(@”The car is: %@ %@”, [myCar make], [myCar model]);
    NSLog(@”The vin is: %@”, [myCar vin]);
    NSLog(@”The color is %@”, [myCar color]);

    [myCar release];

    [pool drain];

    return 0;
    }

    There is a notification by NSLog for color and the myCar set color. The notification says “SimpleCar may not respond to color”. Can you help me understand what I am doing wrong?

    • AJ says:

      Hi Dave,

      I believe your code has a few issues. First, in CarColor.h you define a property called color to be readOnly, which means that you cannot define a setter for it in CarColor.m. Secondly, since CarColor inherits from SimpleCar it (CarColor) would have everything from SimpleCar plus what it itself defines (the color property in this case). However, the reverse is not true. In other words, SimpleCar doesn’t know about CarColor’s color property. And, since myCar (in main.m) is an instance of the class SimpleCar, you cannot pass the setColor message to the myCar instance. If, however, you declared myCar as an instance of CarColor (and assuming you fixed CarColor) then you could pass myCar the color message. Hope that helps!

      ~AJ

  21. Art Pineda says:

    ok help: how do I implement this to the main file.m ???? i can’t use the same set/get invocation because it’s called and generated in the @property? EX: [myCar setVin:newVin]; ?

    //interface

    @property(readwrite, retain) NSString* make;
    @property(readwrite, retain) NSString* model;
    @property(readwrite, retain) NSNumber* vin;

    //implementation

    @implementation game
    @synthesize make, model, vin;
    @end

    //main.m
    int main (int argc, const char * argv[]) {
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

    game *myCar = [[game alloc] init];

    NSNumber *myVin = [[NSNumber alloc] initWithInt:123];

    [myCar setVin:myVin];
    [myCar setMake:@"Honda"];
    [myCar setModel:@"Accord"];

    NSLog(@”The car make is: %@.”, [myCar make]);
    NSLog(@”model: %@, vin: %@.”, [myCar model], [myCar vin]);

    [myCar release];

    [pool drain];
    return 0;
    }

    • Art Pineda says:

      Obviously i’ve missed the header information and variables that go on the .h file but that’s not the point sorry. :)

      • Art Pineda says:

        Ok fixed it.

        //interface

        @property(readwrite, retain) NSString* make;
        @property(readwrite, retain) NSString* model;
        @property(readwrite, retain) NSNumber* vin;

        //implementation

        @implementation game
        @synthesize make, model, vin;
        @end

        //main.m
        int main (int argc, const char * argv[]) {
        NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

        game *myCar = [[game alloc] init];

        NSNumber *myVin = [[NSNumber alloc] initWithInt:123];

        NSLog(@”The car make is: %@.”, myCar.make=@”toyota”]);
        NSLog(@”model: %@, vin: %@.”, myCar.model=@”celica”,myCar.vin=myVin;

        [pool drain];
        return 0;
        }

  22. Taylor says:

    Is an object and a subclass the same thing?

  23. mala says:

    u did mistake in one place.

    - (void) setModel: (NSString*)setModel;

    instead of newModel u give setModel

  24. Niv says:

    hey ,before i ask my question i must say that your tuts are really helpful and i’m enjoy of reading them.

    to my question- i just didnt get how did you change all the implemention with the long code before we start to using @synthesize, on one line of @synthesize make ,model ,vin;

    i didnt understand it and its got me crazy..

    help me with that plx …

  25. M Burnett says:

    I’m just a beginner to learning Obj-C and I’m just reading this code for the first time, but when you use @property and @synthesize, can you still use [self setMake:newMake]; and [self setModel:newModel]; in the set method that takes two arguments, since there is no longer a setModel method?

    Thanks for clarifying!

    • Bill says:

      Yes, you can call the methods. They exist in the compiled code.

      In the interface, @property … declares that you intend for a property to exist, and specify the name.

      In the implementation (.m file), @synthesize … tells the compiler to generate the getters and setters for the property.

      So the methods exist, just as if you had written them manually yourself. @synthesize is your directive to the compiler to save you the work and write them “on the fly” as the program is compiling.

  26. HI
    I AM A BEGINNER IN DEVELOPMENT AND I WAS INTERESTED
    IN FINDING A CHART THAT WOULD TELL YOU THE COMMANDS AND WHAT THEY DO
    JUST TO MAKE IT EASIER
    AND IF SO WHERE CAN I FIND THIS CHART

    THANKS YOUR WEBSITE HAS BEEN A GREAT HELP

  27. Poul says:

    My solution: (not sure if its the right way of doing it, feedback on errors are more then welcome)

    - – - SimpleCar.h – - -
    #import

    @interface SimpleCar : NSObject {
    NSString* make;
    NSString* model;
    NSNumber* vin;
    }

    @property(readwrite, retain) NSString* make;
    @property(readwrite,retain) NSString* model;
    @property(readwrite, retain) NSNumber* vin;

    - (void) setMake: (NSString *)newMake
    andModel: (NSString*)newModel;

    @end

    - – - ExtendedCar.h – - -
    #import “SimpleCar.h”

    @interface ExtendedCar : SimpleCar {
    NSString* color;
    }

    @property(readwrite, retain) NSString* color;

    @end

    - – - SimpleCar.m – - -
    #import “SimpleCar.h”

    @implementation SimpleCar

    @synthesize make, model, vin;

    - (void) setMake: (NSString*)newMake
    andModel: (NSString*)newModel {

    //reuse methods from earlier
    [self setMake:newMake];
    [self setModel:newModel];

    }

    @end

    - – - ExtendedCar.m – - -
    #import “ExtendedCar.h”

    @implementation ExtendedCar
    @synthesize color;

    @end

    - – - main.m – - -
    #import
    #import “ExtendedCar.h”

    int main (int argc, const char * argv[])
    {

    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

    ExtendedCar *myCar = [[ExtendedCar alloc] init];
    NSNumber *newVin = [NSNumber numberWithInt:123];
    NSString *newColor = @”Red”;

    [myCar setVin:newVin];
    [myCar setColor:newColor];
    [myCar setMake:@"Fiat" andModel:@"Stilo"];

    NSLog(@”The car is: %@ %@”, [myCar make], [myCar model]);
    NSLog(@”The vin is: %@”, [myCar vin]);
    NSLog(@”Color of the car is: %@”, [myCar color]);

    [myCar release];

    [pool drain];
    return 0;
    }

    (not really sure if i removed the direct accessibility of the ‘parent’ class SimpleCar)

  28. Mark says:

    In XCode 4, you can’t create a .m file from a template. The only way to find out what needs to be in the .m file is by downloading the source from this page and looking at the code. To allow you to continue the tutorial without downloading the code, here’s what to do.

    Choose from the menu File/New File…

    Choose Mac OS X/Other/Empty and click on Next.

    Type the filename next to Save As and make sure that the file extension is “.m”, for example SimpleCar.m.
    Specify the main folder of your project next to Where.
    The Group should be the only non-standard file group (not FrameWorks, Products or Supporting Files); this is the group where main.m resides.
    In Add to targets the only executable needs to be checked.
    Now you can click on Save.

    The first line of your new file needs to be:

    #import “SimpleCar.h”

    if you created a file SimpleCar.h earlier in the tutorial. Otherwise you use whatever file name you used. Below this line, you write

    @implementation SimpleCar

    @end

    The tutorial tells you to copy part of your .h file and paste this between the latter two lines. From there, you can now continue the tutorial.

  29. luke says:

    Hi, Thanks for your tutorial.
    I am trying to add a button and label based on your code. but the result can be displayed on NSLog, but on label.text?

    label.text=@”My car is: %@ %@ %@”,[myCar vin], [myCar model], [myCar make];

    on iphone simulator, it comes : My car is: %@ %@ %@

  30. Sharat Achary says:

    I am glad that I came across your tutorials. Your explanations along with analogies are great. I am just about to start with Objective-C and your article are of great value for a totally novice like me over this language Obj-C, moreover all these years I had ActionScript 3.0 as my world, but now I have another Universe to explore !

    Great article and a good resource… bookmarked !

    Humble Regards,
    Sharat

  31. Lalitya says:

    Thankyou for your post, It is very helpful for me to get started with objective-c

    Regards,
    Lalitya

  32. Technique says:

    i cant compile the downloadable code or the version i wrote??? this is the error form the downloadable one in my terminal

    gcc CarClassTest.m -o CarClass
    Undefined symbols:
    “_OBJC_CLASS_$_SimpleCar”, referenced from:
    objc-class-ref-to-SimpleCar in cceoboJa.o
    “_OBJC_CLASS_$_NSAutoreleasePool”, referenced from:
    objc-class-ref-to-NSAutoreleasePool in cceoboJa.o
    “_objc_msgSend”, referenced from:
    _main in cceoboJa.o
    _main in cceoboJa.o
    _main in cceoboJa.o
    _main in cceoboJa.o
    _main in cceoboJa.o
    _main in cceoboJa.o
    _main in cceoboJa.o
    _main in cceoboJa.o
    _main in cceoboJa.o
    (maybe you meant: l_objc_msgSend_fixup_release, l_objc_msgSend_fixup_alloc )
    “_objc_msgSend_fixup”, referenced from:
    l_objc_msgSend_fixup_alloc in cceoboJa.o
    l_objc_msgSend_fixup_release in cceoboJa.o
    (maybe you meant: l_objc_msgSend_fixup_release, l_objc_msgSend_fixup_alloc )
    “_OBJC_CLASS_$_NSNumber”, referenced from:
    objc-class-ref-to-NSNumber in cceoboJa.o
    “___CFConstantStringClassReference”, referenced from:
    cfstring=Civic in cceoboJa.o
    cfstring=Honda in cceoboJa.o
    cfstring=The car is: %@ %@ in cceoboJa.o
    cfstring=The vin is: %d in cceoboJa.o
    “_NSLog”, referenced from:
    _main in cceoboJa.o
    _main in cceoboJa.o
    ld: symbol(s) not found
    collect2: ld returned 1 exit status

  33. Technique says:

    Sorry i understand. it works when complied in the xcode builder it self and creates an executable file. Thank you

  34. Jordan O says:

    Great tutorial, but I think there is a mistake in your output. It should say something like: “The car is Honda Civic. The vin is: 123″.

    not: “The make of the car is; Honda”

    Besides that, great tut

  35. Michael Stelly says:

    Ok,
    What am I doing wrong? I copy/pasted the interface code as described. But the build fails with the error

    “Xcode/SimpleCar/SimpleCar/SimpleCar.h:9:9: fatal error: ‘cocoa cocoa.h=”"‘ file not found [1]“. I installed Xcode with the default settings. Why can it not find the cocoa.h file? That makes no sense.

  36. Bob Rodes says:

    I notice that at the top of this exercise you mention that we are importing cocoa.h. I notice that when going through your example, I import Foundation.h rather than Cocoa.h. I assume this is because we have selected Foundation as the type of class. I also assume that this may not have been the behavior when you wrote this, given the volatility of the features in Xcode.

  37. Avinash says:

    How can we compile the objective c .m file code in gcc in linux….?

    Can anybody give a complete working “Hello World ! “code of objective c which can easily be compiled in gcc…
    please also give the commands which have to be used for compiling hello.m file in gcc in linux……

  38. Josh says:

    Great tutorial!
    Thanks a lot!

  39. Umesh says:

    open the gcc type like

    gcc -o prgname.m prgname1

    if no errors are displayed……

    ./prgname1

  40. Tatang says:

    Love your tutorial!!!

    One thing I want to ask… I import “SimpleCar.h” on my main and it doesn’t work.
    I tried import “SimpleCar.m” and worked.
    Why is that?
    Anything that I have to do to make this work?

    Thanks

  41. Fox says:

    I’ve been searching for a simple guide to beginning programming, looked through bookstores and online, and I have to say not even my university lectures do it as well as this guy. Thanks alot for these tutorials Dan, they’ve helped alot more than you can imagine.

  42. Aaron says:

    hi,

    at the beginning of the assignment you say do a command to create a .h file to edit. your says
    #import but mine says ?

    what am i doing incorrect?

  43. Simon says:

    @Tatang – I had the same problem with importing SimpleCar.h into my new subclass interface file.
    I kept getting ‘file or directory not found’ but it worked when I used copy & paste to get the #import “SimpleCar.h” line from the SimpleCar.m file. I had already looked carefully at spelling and capitalization, so I really can’t say why it wasn’t working. I had copied all the code from the tutorial rather than typing it myself, so I wonder if that had anything to do with it.

    Using XCode 3.2.6 on Snow Leopard.

  44. Awais says:

    hi……..
    there is a error if anyone can help me
    when i declare
    variables like
    NSString* model
    there is a error
    it says
    cannot declare a variable inside interface….
    what is this error and what i m doing wrong……..?????
    plz do tell me………….

  45. Talal says:

    @awais,
    bro, use ‘@end’ (without quotes) at the end of file

  46. cyrus says:

    Hi, I’ve been looking through these tutorials, and so far it is amazing. The screenshots and the way you explain it, it is truly amazing. I do wish if you can make it a bit easier, or make a video version, or something like that. Could you also help me out on this project i’m doing at my school. I am planning to make a simple tapping game. I would hope for some feed back asap. Thankyou>

    • Awais says:

      tell me more about the game its feature and processing actually m also new at this so may be i can learn at the same time help u out so its kind of learning for both of us….

      • cyrus says:

        The game I’m thinking to game is like the bubble tap game
        where you tap as many bubbles as you can in this specific time limit.
        Thats what I want to create for now, please e-mail for further on notices if you can

  47. Diane says:

    When I follow the instructions exactly as above, I get 4 error messages on each line that starts with a ‘-’.
    The first error states, “Expected member name or ‘;’ after declaration specifiers.”

    What am I doing wrong?

    Thanks,
    Diane

    This is what my code says, in the simpleCar.h file

    #import

    @interface SimpleCar : NSObject {
    NSString* make;
    NSString* model;
    NSNumber* vin;
    }

    // set methods
    – (void) setVin: (NSNumber*)newVin;
    – (void) setMake: (NSString*)newMake;
    – (void) setModel: (NSString*)setModel;

    // convenience method
    – (void) setMake: (NSString*)newMake
    andModel: (NSString*)newModel;

    @end

  48. Dipillu says:

    Awesome series so far.Just as a side not it will be nice if you updated the code to match ARC (Auto. Reference Counting) specs. as it will give beginners a hassle trying to find what is wrong with their code.I had to look it up on the Help files and apparently its a new feature on Xcode 4.2 to improve Data Management.mesages like [vin release] and [NSAutorleasepool alloc ](which has been replaced by an @autoreleasepool block) can’t be used again.Thanks once more!

    PS- If there is anyway I could override ARC please let me know!

  49. craig says:

    when I copy the code

    @interface SimpleCar : NSObject {
    NSString* make;
    NSString* model;
    NSNumber* vin;
    }

    // set methods
    – (void) setVin: (NSNumber*)newVin;
    – (void) setMake: (NSString*)newMake;
    – (void) setModel: (NSString*)setModel;

    // convenience method
    – (void) setMake: (NSString*)newMake
    andModel: (NSString*)newModel;

    @end

    when I build it says build fail, here is the screenshot https://skitch.com/runrunforest/8subk/screen-shot-2012-04-29-at-12.44.58-am

Add a Comment

To add a code snippet to your comment, please wrap your code like so: <pre name="code" class="html">YOUR CODE</pre>. You can replace the class name with "js," "css," "sql," or "php." If there are any "<" or ">" within your code, please search and replace them with: &lt; and &gt; respectively.