JayData.org

Creation of a hybrid mobile application, part 3

Author: Daniel Jozsef July 23rd, 2012

, , , , , ,


In the last post, I went through the basics of creating a PhoneGap project for iOS, and now as promised, I will go through the basics of Objective-C programming, and JS debugging inside PhoneGap.

Objective-C boot camp

Assuming that you come from a JavaScript, JAVA or .NET background, Objective-C can be a very confusing language to wrap your head around. However, once you understand the “NeXT” way of thinking, you will be fine, contrary to the first impression of many, this language is not rocket science.

For a little history, Objective-C was an obscure language until it was chosen for UI programming at NeXT, the company Steve Jobs founded after he was fired from Apple in the ’80s. When Steve returned to Apple and brought the language with him, its road to stardom was paved. However, there is something you must understand about Objective-C.

It was first created in 1983, the same year C++ was born. All languages you might consider “normal” today, JAVA, JavaScript, C#, even PHP are, to various degrees, children of C++. Objective-C took a different evolutionary route, and is the sole member of its remarkable bloodline. If it were an organism, we would call it a living fossil.

Contrary to C++, which built its object-oriented paradigm on the C struct, Objective-C retained C as an unchanged whole, and added an object-oriented layer based on the (now extinct) language SmallTalk. So the first lesson is that Objective-C is ANSI C. If you know how to do something in ANSI C, you can do it in Objective-C the same way.

Objective-C is not managed code in the sense JAVA or .NET is, but it does come with a runtime component. The only thing you need to know about this is that it helps mostly in memory handling, which is a bit more hassle than in true managed languages, but a lot less so than in C++ or plain ANSI C.

Objective-C code uses the same modular philosophy as C++ and ANSI C, with header and implementation files. Header files use the standard .h extension, while implementation files are .m. Classes consist of an interface and an implementation, with the interface in the .h file. You can “repeat” the interface in the .m file as well, which is the only way to make methods private in Objective-C (ie. you only include the “public” methods in the .h file, and the “private” ones only in the .m file).

Declaring classes and methods

This is how the interface of an Objective-C class looks like:

NSObject is the base class of the Objective-C runtime, similar to Object in .Net or JAVA. All classes you declare must inherit from either NSObject, or one of its child classes.

The following brackets would hold the fields of the class, with similar syntax to a C struct, but it is considered an antipattern to declare the instance variables (fields) in an interface, usually you declare them in the implementation.

Following the closing bracket, you give the method declarations. And this is where things become weird. Method calls in Objective-C are called messages, and true to its name, methods are very “eloquent”. What you could consider the method name is interspersed with the arguments, with argument types given in brackets before the argument names.

There is no overloading, instead similar methods with different argument types are named accordingly, as you can see in the above example as well. In C#, these two methods would look like this:

The return type is given in the bracket prefixed to the method name, and the – at the beginning of the line signifies an instance method. Class (ie. static) methods are prefixed with a + sign.

Calling a method (sending a message) looks like this:

Let me explain. The square brackets signify a method call. First comes the pointer to the class instance. (With classes, you only ever use pointers, so you can safely forget about the pointerness, and just treat it as a reference object similar to Java.) Then the message, which, in this example is to call the first method of the class with 5 and “Hello World!”. The “at” sign in @”Hello World!” tells the compiler to create a constant Objective-C NSString object as opposed to a C character array.

The value of this expression is the return value of the method, a reference to an NSString object. You can also safely embed ANSI C calls in Objective-C messages, or Objective-C messages in ANSI C calls like this:

(Oh by the way, in Objective-C, it is customary to use YES and NO as boolean constants.)

The implementation of a class looks similar to the interface, but here you include the body of the methods as well:

And this is pretty much all you need to get you over the gap and into the realm of Objective-C. Naturally it is not all of the language, but it’s the most confusing part of it. One more thing left to tackle before giving you some links for further reading, and moving on.

Memory management and object lifecycle

This only pertains to Objective-C objects, any traditional ANSI C data structures you will use must be handled according to ANSI C memory management guidelines. Objective-C uses reference counting for memory management purposes, which basically means that an object “knows” how many references exist to it, and destroys itself when the last of them is severed.

Unless you use a modern improvement to the language known as automatic reference counting (which is, unfortunately, unavailable if you use PhoneGap), you will have to make sure to always “tell” your objects what they need to know about the references you hold to them.

Creating an object looks like this:

Alloc creates the object with a reference count of 1, and init is, well, sort of like the constructor. It is mandatory to always call “an” init, and use its return value as the reference to the object, as it may change its location in certain cases. So this is NOT correct, NEVER do this:

If you wish to override the default “constructor”, or create an alternative constructor, you should override init, or create a new init method. Make sure to call an init method of the superclass!

(While we are here, you should know that the keywords for “this class” and the superclass are respectively “self” and “super”.)

This is why I wrote calling “an” init is mandatory. Let’s imagine that SomeClass can be created from an integer, a string, or can be created empty:

Objective-C is a very convention-oriented language. Init methods and only init methods should start with “init”. This is a convention, not an enforced language rule.

If you own an object, you need to call release on it before you drop it:

The tricky thing is knowing WHEN you own it. Not always. If you call release on an object you do not own, you will get a runtime error. It is really beyond the scope of this post, but Objective-C has a thing called the autorelease pool. You can add objects to this pool, and they will be automatically released when the main loop of the application (or whatever smaller code block you set as a new autorelease pool) finishes. I suggest you read up on this, but the first thing you need to know is when an object you get from a method call is autoreleased, and when not.

If the object was the return value of a method the name of which begins with (or is) “alloc”, “copy” or “new”, then you own it, and will need to call release on it when you are finished with it. If the method name does NOT start with any of these three words, then the object is autoreleased, and you must not call release on it.

(Corollary: If you are creating a class, and return a non-autoreleased object in a method, you MUST name your method according to convention, starting with either “alloc”, “copy” or “new”.)

However, if you want to STORE an autoreleased object, such as place it in an instance variable of an object, you must take ownership of it. This is possible via the retain method:

Naturally, when you are finished with the reference, say, the entire class is being disposed of, or you simply replace it, now you own it, so you can, and need to call release on this object. And this leads us to the final topic, destructors.

To do destructor logic in an Objective-C class, you need to override the “dealloc” method, and release all objects owned by the instance. (And of course make sure to call the dealloc method of the superclass as well!) However, you NEVER directly call dealloc. You only ever call release.

And that is all for today, please have a look at Apple’s official Objective-C programming guide:

http://developer.apple.com/library/ios/#documentation/cocoa/conceptual/objectivec/Introduction/introObjectiveC.html

This turned out longer than I expected, so I’ll be giving you the secret methods of debugging JavaScript in PhoneGap in a few days.


, , , , , ,