Thursday, October 16, 2008

Objective-C Crash Course for PHP developers

I've been dabbling around in Objective-C lately, and I thought I'd share some of my experiences with it. It took some time to get my head around a lot of the basic programming syntax. I thought I'd share some things I've learned, and how it compares to PHP.

First and foremost, Objective-C is a compiled language, whereas PHP is a scripted language. Objective-C requires compiling into a binary before it is executed. There is no need to compile PHP, as the script is interpreted at run-time.

PHP was once strictly a procedural language, but over time many object-oriented language features have been added. Objective-C is an Object-Oriented programming language structure that is built on top of C, which is a procedural language. You can freely mix C with Objective-C (as well as C++), much the same that you can mix PHP procedural functions with PHP objects and classes.

Objective-C is foremost an Object-Oriented language. That means, everything is an object. Even a simple string is an object of NSString. And yes, you can mix C code and use plain procedural functions if you wish. Normally you can do everything you need with objects.

First, a "Hello World" application in PHP, then the same one in Objective-C.

The PHP version:


// HelloWorld.class.php
class HelloWorld
{
// instance variables go here

// methods go here
public function printHelloDate()
{
printf("Hello World! at %s",
strftime('%Y-%m-%d %H:%M:S %Z'));
}
}



// hello.php
include_once('HelloWorld.class.php');
$hw = new HelloWorld;
$hw->printHelloDate;


The Objective-C version:

HelloWorld.h header file:


#import <Foundation/Foundation.h>

@interface HelloWorld : NSObject {
// instance vars go here
}

// class methods go here
- (void)printHelloDate;

@end


HelloWorld.m implementation file:


#import "HelloWorld.h"

@implementation HelloWorld

- (void)printHelloDate
{
NSLog(@"Hello world! at %@",
[NSCalendarDate calendarDate]);
}

@end


main.m file:


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

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

HelloWorld *hw = [[HelloWorld alloc] init];
[hw autorelease];

[hw printHelloDate];

[pool release];
return 0;
}


If you have had any experience programming in C, much of this will look familiar. Objective-C is after all, just an extension of the C programming language, adding in all the OO goodness of Objective-C to the already existing C syntax. I'm going to refer to Objective-C as OC from here on out.

Notice that comments are identical in PHP, OC, and C. // for single line comments, and /* */ for multi-line comments. Easy enough. Now, lets take a look at the OC code, starting with the header file:


#import <Foundation/Foundation.h>


#import is much the same as include_once() in PHP. If a file gets imported more than once, it is ignored.

OC is made up of header files (.h) and source files (.m) Typically, each header file is paired with a source file. The header file declares the instance variables and methods of your classes, whereas the methods are implemented in the source (.m) file. You need only import the .h file, as the .m file is compiled by XCode automatically.

Foundation.h is an existing OC framework of classes. It includes much of the fundamental objects you will want when developing Objective-C. There are many other frameworks to choose from too. The core of PHP is procedural code, so there is no "foundation" to include. All of the basic PHP functionality is available at the outset of any PHP script (excluding special extensions and libraries of your own.)


@interface HelloWorld : NSObject {
// instance vars go here
}


The @interface line describes the name of your class, and also describes what object it is inherited from. Here we have a class named "HelloWorld" and it inherits NSObject, which is the most basic of objects. It is the top object of the inheritance tree. In PHP, there is no need to declare what object an non-extended class is inherited from.

In the curly braces of the @interface line, you declare what instance variables your class will contain. In our example, we have none declared.


// class methods go here
- (void)printHelloDate;

@end


After the curly brace and before the @end symbol, you declare your class methods, and the arguments they may take. The minus "-" at the beginning of the line declares that this is an instance method. If it began with a "+" it would be a class method. In PHP the "+" methods would be referred to as static methods. That is, a method called directly from the class, not from an object instance.

(void) is the value that is returned from the method. This method does not return a value.

@end defines the end of the method declarations.

And now the implementation (.m) file:


#import "HelloWorld.h"


We import our HelloWorld.h header file.


@implementation HelloWorld


Between the @implementation and @end lines, we implement the methods of our class.


- (void)printHelloDate


This is an instance method, denoted by the "-" at the beginning. A "+" would have denoted a class method, or "static" method in PHP jargon. This method does not return anything, so (void) is used as the return declaration.


{
NSLog(@"Hello world! at %@",
[NSCalendarDate calendarDate]);
}


This is the body of our method. NSLog is the OC equivalent to the PHP's and C's printf function. %@ is a placeholder for our string object. NSCalendarDate is a class from the Foundation.h framework, and we are calling the calendarDate method of the class. It will return a string object containing a date for our NSLog.


@end


This marks the end of our implementation methods.

And now for the main.m file:


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


Here we import our Foundation.h file. (Note we could have left this out, since the HelloWorld.h file imports it already.) Then we import the header file of our HelloWorld class.


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


As in C, every OC program must have a main() function. This is where the compiled binary will begin its execution, passing in any arguments given from the command line. In PHP, arguments to a script are captured in the $argv variable.


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



This is part of the memory management of OC. Every object in OC retains a count of how many references are attached to it. When an object is first instantiated, a reference count of 1 is placed on the object. Each time the object is retained, its reference count is incremented. Each time it is released, it is decremented. Once the ref count reaches zero, the object is destroyed. The autorelease pool is an OC convention used for memory management. When you autorelease an object (as opposed to just releasing it), it gets added to the pool of objects to be released at a later time. This way if something else needs to pick up your object before it is destroyed, it can, and you don't have to remember to release it again. OC 2.0 also has garbage collection features that help automate the tedious task of memory management. In PHP, memory management is automagically handled for you.


HelloWorld *hw = [[HelloWorld alloc] init];


This is where your object is instantiated. [HelloWorld alloc] means we are calling the static method "alloc" of the HelloWorld class (a special method available to all OC classes.) alloc does the memory allocation for your object. Then, the init method is called of the instantiated object. This is much like the __construct() method of PHP objects, where initialization is handled, as well as initialization of any superclasses. The object is then given a pointer (of type HelloWorld) named *hw. Now we reference our object with hw from here onward. Note that in OC all objects require pointers to reference them.


[hw autorelease];


Here we hand our object to the autorelease pool. Now I don't have to remember to release it later, and it's still available for me to use. The autorelease pool is kind of pointless for our HelloWorld app, but since the autorelease pool is an integral part of OC programming, I left it in. (I could have just did [hw release] after I was done with it.)



[hw printHelloDate];


This is where we call the printHelloDate method of our class. In OC jargon, they call this a "message". I don't know exactly why, it's just calling a method of the object. When you see [object message] in OC, that is exactly what it is. The object is on the left, the message (method name) is on the right.

While we're on the subject of calling methods, You may see methods with parameters, but in OC they are named. Here is an example:

PHP:


$rectangle->setSize(10,20,true);


Objective-C:

[rectangle setX:10 Y:20 visible:YES]


Here you see exactly what the parameters are for. In PHP I may have guessed that the first two params were X and Y, but the third would be a mystery without digging into the class. In OC, I can plainly see the first arg is X, the second is Y, and the third is setting the visiblity. Also in OC, you will typically see YES and NO used for booleans, not true and false.

One other tidbit: in Objective-C, the parameter names are part of the method name. So in PHP, the above method name is setSize(), whereas in Objective-C, the method name is setX:Y:visible.


[pool release];


And here we are releasing the autorelease pool, which will inevitably clean up our object from memory.


return 0;


Our main function is expecting an integer to be returned, so we'll return a zero.

That's about it. If there are errors, send me a comment and I'll get them corrected. Thanks!

11 comments:

trungson said...

Thank you for the detailed walk through. I'm consider learning some Objective-C to create an iPhone app.

kerk said...

Thanks for this post. While I have done lots OO programming and tons of PHP programming I have never used C or C++ so learning Objective-C has my head spinning with some of the syntax. Your post certainly helps.

Rory said...

Very insightful, thank you very much! With this I'm now a lot more cofident about starting out in OC!

Krzysztof said...

It's very useful, thank you.

btw, I think that it should be setSize() in sentence: "...So in PHP, the above method name is getSize()..."
am I wrong?

mohrt said...

Yep, it should be setSize. Fixed.

Kasper A. Svendsen said...

I am pleased to read your post.. Learned alot.. Now able to start develop iPhone apps

Emma said...

seemed like an easy way to lear objective c ..... thank you for posting such an informative post...

PHP Programming

antiver said...

Coming from a heavy PHP/Java and moderate C/C++ background, this gave me what I needed to understand all the new stuff I'm seeing in Obj-C.

Thanks!

yayix said...

exactly what i'm looking for. great tut. thanks!

Ascendant said...

This is really fantastic. I've been wading through a lot of Objective-C documentation, and this really helped explain key concepts the way my brain wants to understand them (which is relating to the language I know best, PHP) Great work!

Cici said...

Thank you for this great overview!
I think you meant "OC" where you said "In OB jargon" once.
Keep up the great work.