Learn Objective C in 30 minutes
Recently I started thinking about writing something simple in Objective C – you know, that weird Apple language used for Mac programming… Not that I’m planning to switch from Ruby to ObjC – I rather treat this as a kind of a challenge (“what, I can’t learn this thing? of course I can!” :), besides, there is no language good for everything, and there are some low-level things that you really shouldn’t write in Ruby, like plugins for Finder, Quicklook, etc. Also, I remember reading somewhere that it’s good for a programmer to learn a new language each year – so, two years ago Python, last year Ruby, this year Objective C? :)
I googled for some quick tutorials, read a couple of them, and I realised that this language is really very simple, it just looks complicated because of that syntax and symbols; but once you start translating everything in your head, it all starts looking very familiar. Of course, it’s a different thing to understand what’s going on in someone’s code and to be able to write your own (for that, you also need to know some libraries…); but in this case, it’s pretty easy to go from “OMG WTF dude what’s this??” to a state when you can look at ObjC code and understand it as if it was written in Java or something else.
I made some notes while I was reading the tutorials, and I’m publishing them here so that maybe someone can learn this faster than I did – it’s just a “diff”, so I didn’t describe in detail anything that is obvious for someone who knows C, Java, Ruby, etc. You can treat this as a kind of poor man’s tutorial… Although I’m warning you that I spent a total of about one day looking at ObjC code, so some of what I’ve written here may not be completely correct, or may even be completely wrong. This is all based on what I read, not on my own experiences (which I have almost none). This product is provided without any warranty :)
The language
- ObjC is a superset of C. This means that all properly written C programs should theoretically compile as ObjC programs without making any changes. Everything that works in C, works in ObjC. ObjC adds some new features to C, including OOP and Smalltalk-like message passing.
- Objective C is a language that is compiled to native machine code, just like C/C++, and that should probably make it faster than Java, Python or Ruby, which run in virtual machines.
- On the other hand, ObjC has a lot of features that make it much more dynamic than C++, and more similar to Ruby or Python. ObjC supports both static typing and dynamic typing, depending on how variables are declared (more about this later). Unfortunately, all that makes it slower than C++. I don’t know how much slower though, I haven’t been able to find a single benchmark… I guess I need to write one myself.
- The newest version of the language is 2.0, which was released recently (with Leopard); it adds some cool new features, like garbage collection, properties, or for-each loops.
Source code
- Files are organized in a way similar to C/C++: there are header files (*.h), which contain interface declarations for classes, and source files (*.m), which provide their implementations. I have no idea why they selected the extension .m – even Google doesn’t seem to know that…
- Update: Thanks to Stack Overflow, I’ve learned that the .m extension means either “messages” or “methods” :)
- In ObjC there are no namespaces like in other languages; instead, to be able to distinguish classes coming from different frameworks, name prefixes are used. For example, a lot of core ObjC classes have the prefix “NS” (NSString, NSObject, etc.), which is short for “NextStep” (it’s a Unix environment created in the 90s, which was used as a base for MacOSX when it was developed).
- Program execution starts in the
int main()
function, as expected. - Headers can be included using
#include
, but it’s better to use#import
, which works just like include, except it never includes the same header twice (so you don’t have to do any stupid#ifndef
/#define
stuff like in C++). - Keywords added by ObjC start with “@” to distinguish them from those from C.
- Programs can be compiled using gcc, like C/C++, but you need to add
-framework Cocoa
to use the ObjC standard library (or, as it is called in ObjC world, “framework”).
Methods
- That’s the single weirdest thing in ObjC. You don’t call methods with
foo.bar
, orfoo->bar
, orfoo-whatever-bar
. You call them with[foo bar]
… andobj.foo.bar
becomes[[obj foo] bar]
. A bit inconvenient IMHO, because when you write a sequence “object method method method …” then at the end you have to go back to the beginning and add an appropriate number of opening brackets to match the closing brackets… But once you install a proper regular expression in your head that changes bracket notation to dots, it at least becomes readable. - Another unusual thing about methods is that parameters in most cases are given labels, which are used in the method call. So method calls with more than one parameter look like this:
[appleStore buyMacs: 2 withRAM: 4 withCPU: 2.66]
This is one of the ideas that were taken from Smalltalk. It does make the code longer, but on the other hand, it becomes much more readable. Besides, it’s quite similar to Python’s
foo=bar
parameters and Ruby’s:foo => bar
, so it’s nothing really new. - The labels actually form the full name of the method. So the method above is referred to as
buyMacs:withRAM:withCPU:
. - Methods can’t be overloaded by parameter type, so there can’t be two methods
foo(int)
andfoo(char*)
. But they can be overloaded by labels, so you can have methodsbuyMacs:
,buyMacs:withRAM:
,buyMacs:withMonitors:
and so on. - The above is often used as a replacement for default parameter values in functions, which don’t exist in ObjC. So if you want the second parameter to have a default value, you must write two methods, one with one parameter, and the other with two…
- Like in Python or Ruby, calling a method that doesn’t exist doesn’t throw a compiler error, but a runtime exception, which can be caught and handled.
- What’s more, calls to not existing methods can be intercepted and handled before an exception is thrown. Does that remind you of something? Ruby’s method_missing, of course! Here, the method that can be used for this is
forwardInvocation:
. - Tutorial authors generally insist that in ObjC you don’t call methods, you “send messages”. I think it’s just a matter of naming, I can’t see how the method calls in ObjC are different that, say, in Python… except the brackets, of course. But I may be wrong. (Methods are also called “selectors” sometimes.)
Data types
- ObjC has both primitive and object types, like C++ or Java. Unlike C++, it doesn’t have value types for objects, only pointers, so there’s no
Foo x
, onlyFoo *x
. - Normal C data types (int, float, etc.) can be used, although that’s probably not always the recommended way. For example, there are types like
NSInteger
,NSUInteger
, orCGFloat
, which are architecture-safe versions of int, unsigned int, float and so on. There is also a class namedNSNumber
used for boxing/unboxing primitive types in cases when we need to pass an object somewhere. - Apart from C strings (
char *
), there are also ObjC strings (NSString
). To create the latter on the fly, use the at sign:@"some text"
. NSStrings can be converted tochar*
usingcString
(deprecated) orUTF8String
methods of NSString (for example, when you need to use them as parameters toprintf()
). - Boolean is called
BOOL
, and its values are… you’ll never guess:YES
andNO
:) - There is a generic type called
id
, which basically means “any object”. This is something likeObject*
, but there’s a “tiny” difference. These two letters are a door to the world of dynamic typing. If you declare a variable asFoo* x
, it works like in C++ – try to call something that isn’t available in class Foo, and the compiler will notice that (although in ObjC it doesn’t exit with an error, it just prints a warning – because sometimes the code may be correct, even if this isn’t obvious for the compiler). But if you declare a variable asid x
, it works like in Ruby – the compiler lets you call anything you want on it, and only at runtime it will be determined if the object can handle that method or not. - Null is called
nil
. And, as in Ruby, apparently you can call methods on it and the universe won’t implode. Even more, you can call any method on it, and it will always return nil – this means that often you don’t even have to check if an object is nil. You just call whatever you want on it, and if it’s nil, it just sits there and ignores you. It may make coding a bit simpler, but on the other hand it probably makes debugging much harder – you don’t immediately get an exception if something which shouldn’t be nil is nil… - For pointers to classes, nil is written in uppercase (
Nil
). Don’t ask me why… - Just like
NSNumber
for ints, there is a wrapper for the nil value – theNSNull
class. You can’t put a nil into an NSArray, but you can put a NSNull there (usage:[NSNull null]
). SEL
(short for “selector”) is a type for pointers to methods. To get a SEL pointer, use the keyword@selector
with the method signature, e.g.@selector(methodName:withArg:)
.- All objects have a method named
description
, which is the same astoString
in Java. - A lot of the built-in object types have mutable and non-mutable versions: there’s
NSString
andNSMutableString
,NSArray
andNSMutableArray
, and so forth.
Classes
- class interfaces (*.h) are declared using the keyword
@interface
:@interface MyClass: NSObject { // <-- NSObject is the superclass // now, a list of instance variables: int foo; ... } // and now - a list of methods: - (void) print; - (void) setValue: (int) v; - (void) setValue: (int) v andAnother: (int) a; - (int) value; - foo; + (int) numberOfInstances; + (void) initialize; // class initializer @end
Method definition syntax is quite different from C/C++, but is rather easy to understand. Methods with a minus sign are instance methods, and those with a plus sign are class (static) methods.
- ObjC uses single inheritance, like Java or Ruby.
- If you don’t mention the returned type explicitly (like in method foo above), the default type is
id
. - If a class has a class method named
initialize
, it is called once at the moment when the class is used for the first time (like static constructors in C#). - Another keyword used in interface declarations,
@class
, is used for forward declarations, like in C++. If you need to mention one class in the interface of another, to reduce coupling between classes you can declare it with@class Klass
instead of#import <klass.h>
. - Class implementation (*.m) is enclosed in
@implementation
…@end
keywords:@implementation MyClass - (void) setValue: (int) v { ... } @end
- Variable declarations don’t have plus/minus signs in front of them, so if you want to have a static variable in a class, declare it using the C keyword
static
in the header file, outside the @interface block (e.g.static int instances;
). - Instance variables are accessed using the arrow operator
->
, e.g.person->name
. - Variable access is set using the keywords
@public
,@private
, and@protected
; they’re used like in C++ or Ruby, not like in Java – you put a keyword before a group of variables, not before each variable. Default access is @protected. Methods, on the other hand, are always public; you can simulate private methods by not adding their signatures to the @interface, writing only implementations in @implementation. - ObjC 2.0 introduced “properties”, which are similar to object properties in other languages:
- Inside @interface, in the method block you declare e.g.
@property int age;
. This works the same as if you manually declared a getter(int) age
(in ObjC getters don’t have a prefix “get”) and a setter(void) setAge: (int) age
. You still have to mention a matching instance variable in the variable block. - Inside @implementation, you write
@synthesize age;
, which generates the implementations of the getter and setter. You can also provide your own custom implementations. - To increase confusion, properties aren’t accessed with
[obj age]
or withobj->age
, but with a third syntax:obj.age
… - Properties can have additional options inserted in parentheses after the @property keyword, like:
@property (readonly) int age;
. The readonly option means that only a getter will be generated.
- Inside @interface, in the method block you declare e.g.
Categories and posing
- In ObjC, apart from inheriting from classes, you can also… add code to existing classes. Even built-in classes. Sounds terribly Ruby-ish, doesn’t it? :) It’s not as powerful as Ruby’s “open classes” mechanism (e.g. you can’t add new instance variables), but it seems nice anyway. Here it’s called “categories” (because if you have a long class, you can divide its methods into several categories and put them in different files), and here’s how it’s done:
@interface ExistingClass (SomeNewName) ...methods... @end
Then you include both the old header and the new header in the implementation file, and voila – you have a class with new methods added.
- There’s also a second, similar mechanism called “posing”. With posing, instead of adding methods to a chosen class, you create a subclass of that class, and then you declare that the subclass should “pose” as the superclass, which means that the old class will just be replaced with the new one. You do that using
poseAsClass
method:
[SubClass poseAsClass: [SuperClass class]];
. - Apparently posing is now deprecated, so it shouldn’t really be used anymore; I’ve just included it here so that you know what this means when you see it.
Loops, conditions and operators
- Those things generally work just like in C –
for
,while
,if
… everything looks as you can expect. - For ObjC collections, you can use Java-like enumerators:
NSEnumerator *enum = [array objectEnumerator]; while (i = [enum nextObject]) { ... }
- In ObjC 2.0, there are also for-each loops, called “fast enumeration” (because it’s apparently more efficient than the old way):
for (Foo *foo in list) { ... }
- Equality checks work similar to Java: the
==
operator compares object identity, and to compare values you need to call a function:[x isEqual: y]
.
Objects
- Inside object methods, the reference to the object is called
self
, like in Python or Ruby. - To call the superclass’s implementations of functions, use the
super
reference. For example,[super foo]
calls super’s version of the method foo on self. - Object creation is two-phase: first you call
alloc
on the class to allocate memory, theninit
(or sometimes a different, specialized initializer) on the object to initialize it; so it looks like this:Mac *box = [[Mac alloc] init];
If I remember correctly, it’s the same in Ruby, but there it happens behind the scenes –
Foo#allocate
andFoo#initialize
are called when you writeFoo.new
. - If you want to have several constructor variants, you can write them like this:
- (ClassName*) initWithParam: (int) one andAnother: (int) two { // first, call any initializations defined in superclass self = [super init]; if (self) { // self could be nil if something went wrong // ... set some instance variables and stuff } return self; // won't work without this }
And then you use it like this:ClassName* var = [[ClassName alloc] initWithParam: 5 andAnother: 6];
Protocols
- Protocols are basically Java’s interfaces – lists of methods without implementation, which can be implemented by classes. Protocol declaration looks similar to a class declaration:
@protocol FooInterface - (int) foo; - (void) bar; @end
- To mark a class as implementing an interface, add the interface name in triangle brackets:
@interface MyClass: NSObject <Printable, FooInterface>
The methods declared in the implemented protocol don’t need to be listed inside the
@interface
declaration. - Like in Java, you can declare variables that point to anything that implements an interface:
id foo = [[MyClass alloc] init];
You can assign any object to variable foo, as long as it implements FooInterface.
- There are also so-called “informal protocols”, which are just lists of methods published somewhere in the documentation that your class has to or can define, but the fact of implementing the protocol isn’t explicitly mentioned in the code. This is often done by adding a category to a class, named the same as the protocol, which contains the required methods.
Memory management
- Old version: like in C, on which ObjC is based, you have to remember about releasing all memory that you allocate, and if you forget about something, you get memory leaks (and if you release too much, you get segfaults).
- New version (since 2.0): ObjC now includes a garbage collector (!), so you just turn on one option in Xcode project settings and forget about memory management :) It’s quite unusual for a fully compiled language to have a garbage collector, and that makes ObjC rather unique.
- But the introduction of garbage collector in 2.0 doesn’t mean that everybody will start using it right now (e.g. it isn’t available on the iPhone yet), so here are a few details about memory management:
- Even without garbage collector, memory management is a bit simpler than in C/C++. The difference is that you don’t have to think about who exactly should be responsible for destroying an object. Every time you store a reference to it, you call
[obj retain]
, which increases its “retain count” (number of references); and when you no longer need it, you call[obj release]
. If this makes the retain count reach 0 (it starts at 1 after alloc/init), the object is released, if not – nothing happens. So every object can have several “owners” and they all dispose of it in the same way. - When an object is destroyed, its destructor – a method named
dealloc
– is called. In this method, you can call release on all references to other objects that you store in that object. You should also call super’s dealloc. - When garbage collector is turned on, all methods like retain, release, etc. are just ignored, and dealloc is not called. Instead, the method
finalize
gets called when an object is garbage collected (like in Java). - Another way to manage memory is something called “autorelease pools”. They’re kind of multi object managers, instances of
NSAutoreleasePool
class, and you can assign objects to them using[obj autorelease]
. Then, when an autorelease pool is released (using[pool drain]
– nice terminology :), it automatically releases all objects assigned to it. - You have to be careful about which objects are already autoreleased when you get them, and which should be (auto)released by you. For example, objects produced not with
alloc
, but using static methods in basic classes like NSString, e.g.[NSString stringWithFormat: ...]
(which is something likesprintf()
), are usually already autoreleased. You can’t call release on them, because this will cause a segfault when the pool tries to release them. The general rule is: when you create an object usingalloc
orcopy
methods, you need to release it, and if you get it through some other means, usually someone else will release it. - With release/retain, you also have to be careful about how you write property setters (if you don’t use
@synthesize
). You have to both release the old object and retain the new one; but you can’t release before you retain, because if they point to the same object, it would be deallocated at the moment of release. So you have to either call retain before release, or check the pointers if they’re not the same at the beginning of the setter, or use autorelease instead of release.
- Even without garbage collector, memory management is a bit simpler than in C/C++. The difference is that you don’t have to think about who exactly should be responsible for destroying an object. Every time you store a reference to it, you call
Reflection
- ObjC is more dynamic than C or C++, despite the fact that it’s really a strongly typed, compiled language. Here are some examples of functions related to reflection:
isKindOfClass
,isMemberOfClass
– like kind_of?, instance_of? in RubyrespondsToSelector
,instancesRespondToSelector
– tells if an object has a specific method (like respond_to? in Ruby)performSelector
– calls a specified method on the object (like send(:method_name))conformsToProtocol(@protocol(FooInterface))
– tells if a class implements a protocol
Exceptions and debugging
- Exceptions work like in every other modern language: they are represented by classes inheriting (usually) from NSException, and you use the keywords
@try
,@catch
and@finally
to intercept exceptions thrown inside a block and handle them. Use@throw e
to throw exception e, and@throw
to re-throw an exception in the catch block (like in Python/Ruby). - Two methods that may be useful in debugging:
NSAssert(x != 0, @"X must not be zero")
– throws exception if x == 0NSLog(@"foo bar %@", x)
– outputs the string (+ some info) on stderr, and also adds the same line to /var/log/system.log (which can be viewed with “Console” application).
And that’s all… if you didn’t know anything about Objective C before, and you did have the patience to read all of this, then I hope you have now some idea what this is all about. Anyway, now you shouldn’t run away screaming when you see some ObjC code somewhere… At least I don’t do that anymore ;)
Bibliography
- http://cocoadevcentral.com/d/learn_objectivec/ – tutorial
- http://ktd.club.fr/programmation/fichiers/cpp-objc-en.pdf – tutorial
- http://en.wikipedia.org/wiki/Objective-C
- http://www.macdevcenter.com/pub/a/mac/2003/04/28/objective-c.html – about id type and dynamic typing
- http://www.theocacao.com/document.page/510 – about ObjectiveC 2.0
36 comments:
xitrum
thank you for your sharing. Thanks
ndgiang84
intelligent and humorous :)
Alec Gorge
So very useful. Answered ALL of my questions! For example, I was just wondering: how do I access a class variable. You are the only person to answer it!
Tetek
Great stuff, thanks !
doan the hien
thank you for sharing this one
ania
Awesome tutorial, Kuba, thanks!
luuk
good stuff, thanks a bunch!
radarek
Nicely written!
toaninfo
Very informative. Thanks.
FancyEmma
Been developing in Objective-C for a little under a year now, and I still got quite a lot out of this article, and truly if nothing else it's a very succinct overview of the language. Thank you for taking the time and writing it! :-)
parag
good stuff
Amit Kabra
Nice stuff, I will surely use it for reference for the time to come.
Since I am new to objective c, I don't know you have left anything , so is everything covered here ?
chirag
awesome tutorial!!!!!!
ndq
Thanks very much for your sharing. It's helpful for me.
Kuba
@Amit Kabra: of course it's never 100%, especially since the language is constantly evolving... For example, when I wrote this article ARC (automatic memory management) didn't exist, and the last version in OSX 10.8 / iOS 6.0 added a lot of cool stuff like array/hash literals. (Now that I think about it, I could update this article with the new things that were added since then...)
tauseef khan
Really Awesome Tutorial ....
ALL IN ONE :D
Thanks Jakub Suder :-)
keep it Up ! (y)
tauseef
Thanks For the Nice Tutorial .
Nice Blog :)
tauseef khan
I would like to subscribe your blog. please tell me how i can subscribe your blog... I "followed" you on 'twitter'
Kuba
@Tauseef: the apple in the footer is a link to the RSS feed.
jaimin
Very informative, and good read!
Thanks for sharing it.
Durai
I jus happened to be stumbled upon you site...It's really clear and simple...I wish i'd have visited site when i first started learning this language...
AnyHow fruitful effort...
Tunvir rahman
Its really a great site for beginner in objective C. Its contain all the preliminary concepts of objective C. thanks
Jan
A great tutorial for a fast start :) could you please dosome more for other langauges please?
but here is a tip: you said "Tutorial authors generally insist that in ObjC you don’t call methods, you 'send messages'" which is true because in objective-c when you call a function the dissassembly will tell you that you actually call the method objc_msgSend which will do some checks at runtime about the call and then calls the method.
I hope this is helpful :)
Anand India
Great tutorial very useful thank u a lot :) keep sharing like this tutorial
Agara
This is a great and succinct tutorial.
Before taking the iPhone Apps programming class for fun, I wasn't aware that Apps are written in Objective C. Of course, I knew about objective C and SmallTalk80!
As I have done lot of development using C, and knowing C++ and Java it was not a problem to learn objective C. However, lot of my classmates are struggling as they know only Java and try to write Java programs in objective C! This tutorial will be a great asset for them.
Thank you for simplifying Objective C. I echo another commentators request - please write more tutorial like this for other programming languages.
Your effort is greatly appreciated and thank you!
Please write more tutorials like this for other languages like Java, C++, Ruby, PHP, Python and Perl!
My interest is in comparative programming languages and their genesis!
Krishna Verma
Thanx Dear it really seems that yow found cream stuff from many resources and thanx for sharing it here. It is very beneficial.
Amir Habibi
Thank you.
Xavi
Great! Thanks a lot!
Olawale Ogunkeye
thanks for this info.
Apoorv Parijat
Amazing piece. Thanks a bunch for writing this down.
Allan Kenneth Ang
Great piece of work!
TAR
Nicely written!!! THANKS
Tammi
Great stuff! Thank you for this.
Albiggy
How many versions of objective c are there in total??
Kuba
@Albiggy no idea, but you only need to care about the last one :) There weren't any major changes recently, they only add some nice small features from time to time, but you don't have to use them immediately.
See this post from 2013: https://mackuba.eu/2013/04/20/whats-new-in-objc/
Lucian
Thanks for the intro to objective c.