Thursday, May 20, 2010

#6, Introduction to Objective-C and Cocoa

This post is a couple of days early because I'm off to visit my mom all the way on the other side of the world, after 2+ years (and to see some people after 15+ years!). I'm going to talk about programming again (with you here, not with my mom). What I really wanted to do was jumping into more exciting 3D graphics programming stuff but as any of my IMD-2004 students can tell you, you have to learn to walk before you can run! So let's start with fundamentals of programming for Mac/OSX.

As I told you before, OSX programs are written on top of a set of APIs, from OpenGL to Quartz and Carbon, all the way up to Cocoa. You can write C/C++ code to work with lower level ones, but what Apple is encouraging developers to do is to use the new API, Cocoa, and its programming language, Objective-C. And I thought I'd go through them kinda from top to bottom, starting with the new kids on the block, Cocoa and Objective-C. In a matter of speaking, Apple and Microsoft went through a similar process; they both created new frameworks with new programming languages (for Microsoft it is .NET and C#), but while Cocoa is more like a high-level API on top of others like OpenGL and Quartz (although it can bypass them sometimes), .NET is a completely new application structure, kinda like a virtual machine (i.e. Windows and .NET executables have completely different formats). The differences are even more clear when it comes down to the language. Both Objective-C and C# are new languages which are not theoretically tied to Cocoa or .NET, but in practice you use Cocoa and .NET libraries for them almost always. While C# continues the well-known syntax and notations of C/C++, Objective-C defines its own new object oriented structure and syntax on top of C. To understand OSX programming, we first need to learn the language.

Before I move forward, here are a few useful links:
* http://developer.apple.com/mac/library/documentation/Cocoa/Conceptual/ObjectiveC/Introduction/introObjectiveC.html
This is from Apple Developers' Library. Not a very good easy-to-use thing.
* http://en.wikipedia.org/wiki/Objective-C
Wikipedia is always a good for starting point
* http://cocoadevcentral.com
This is a pretty good place to start actual coding but the description is for older versions of Interface Builder (see AppController in the Cocoa section of this post)
* http://www.otierney.net/objective-c.html
This site is ok
* http://mobileappmastery.com/objective-c-tutorial
And this is not bad either

=========
Objective-C
=========

It all stated with C, the mother of all popular programming languages (in your face, Lisp programmers :-). C uses a well-known syntax and structure that many other languages adapted, such as the way functions and variables are defined. C++ is a superset of C and tries to look like C as much as possible. For example, classes look like C structures, function calls are the same way except they can have the object added before the function name, and C++ continues with the header/implementation file structure. C# and Java use many of these but they both got rid of header files ;-) Objective-C designers on the other hand made a different decision. Similar to C++ and unlike C# and Java, Objective-C is a superset of C. This means you can have C code mixed with your Objective-C code, both in the same file (.m) and as a separate file (.c). Objective-C uses the same idea of header files (.h) for class definition. But the similarity to C++ ends right there. The syntax is almost completely different. Whose brilliant idea was that? Well, if you want to get into more behind-the-scene technical stuff, the SmallTalk style is claimed to have some advantages over Simula style, such as ease of dynamic binding but I'm not buying that.

The first thing to know about Objective-C is how to define classes. Here it is:
@interface classname : baseclassname
{
// instance variables
}
+classMethod1;
+(return_type)classMethod2;
+(return_type)classMethod3:(param1_type)param1_name;
-(return_type)instanceMethod1:(param1_type)param1_name :(param2_type)param2_name;
@end

Objective-C uses the keyword interface for class, class method and instance method are the names for static and normal member functions, and are specified by + and - signs. Finally the type is inside () not the parameters which are listed after : . Here is the same code in C++:
class classname : baseclassname
{
public:
// instance variables

// Class (static) functions
static void* classMethod1();
static return_type classMethod2();
static return_type classMethod3(param1_type param1_name);
// Instance (member) functions
return_type instanceMethod1(param1_type param1_name, param2_type param2_name);
};

Here is an example with the implementation file:
//Integer.h
#import //import is the same as include

@interface Integer : Object
{
int integer;
}

- (int) integer;
- (id) integer: (int) _integer;
- (id) add: (int) _integer;
@end

//Integer.m
#import "Integer.h"

@implementation Integer
- (int) integer
{
return integer;
}

- (id) integer: (int) _integer
{
integer = _integer;

return self;
}

- (id) add: (int) _integer
{
integer += _integer;

return self;
}

- (id) hello
{
printf("hello!\n");

return self;
}
@end

Objects are instances of classes and are created using the "new" keyword:
//Objective-C: classname * objectname = [classname new];
//C++: classname * objectname = new classname;
Integer * x = [Integer new];

And finally, you access members:
//function call
Integer * x = [Integer new];
[x hello]; //calling the method "hello"
[x integer : 8]; //calling method integer with parameter 8

As you can see in the method "hello", you can use standard C (including struct) in Objective-C.

=========
Cocoa
=========

Cocoa is based on NextStep framework, hence the NS in all class names. You can use OpenGL, Quartz and other APIs from within your Cocoa application which are usually made using Xcode and Interface Builder. Now here is another strange design choice: Xcode is supposed to be an Integrated Development Environment, but Interface Builder is a separate program. When you modify your application UI in Interface Builder, you have to save it and go back to Xcode and recompile. Not to mention (again) that they are both suffering from bad UI themselves! But once you get past the UI, creating your first Cocoa application is pretty easy. Here are the steps for a simple NotePad:
1- Start Xcode and go to File/New Project
2- Select Cocoa Application, give it a name and select a location
3- Build and run your program to see an empty form (then quit the program!)
4- In Xcode, under Groups and Files, select Interface Builder Files and double-click on the one with nib extension
5- Now you are in Interface Builder and should be able to see your form (app), its menu, and the Library window, and the Document window (and possibly other things).
6- From Library, select Text View (you can search for it in the search box at the bottom of Library).
7- Drag and drop the Text View to your form and resize it if you want (notice that your menu has a Format item by default that will allow you to format text)
8- Save your Interface Builder file, go back to Xcode, build and run

If you compare this to C# and .NET, the process is pretty much the same, except that the default application in C# doesn't have a menu and formatting needs to be handled by the programmer. Although .NET framework does have classes for showing a Font box but a few lines of code are needed to create the UI objects and handling their event to show the format controls and apply the user selection.

Now let's see how we add more stuff to our simple Cocoa application. For example, we want to add a button that clears the text. Here are the steps:
1- In Xcode, click on Classes in Groups and Files window, then go to File/New File…
2- Select Objective-C Class and name it AppController. Now you have two new files AppController.h and AppController.m. This class will control an Interface Builder object in your application.
3- In AppController.h, add a variable of type IBOutlet to your class. This is a link to Interface Builder. Also add a method that's supposed to clear the text view.

@interface AppController : NSObject {
IBOutlet id textView; //outlet
}
- (IBAction) clearText: sender; //method for clearing
@end

4- In AppController.m, write the implementation of the new method.

@implementation AppController
- (IBAction) clearText: sender
{
[textView setString: @" "];
}
@end

5- Open the Interface Builder by double-clicking on the .nib file (see step 4 in for simple notepad)
6- In the Library window, select Classes, find AppController and drag/drop it to the Document window to create an instance of that class. In previous versions you need to drag AppController.h from the Xcode window and drop it on the Interface Builder document window.
7- Hold the Control key and drag/drop the AppController from Document window to the text view object in your form (design window), and select textView from the list. This was a little different in older versions of Interface Builder so be careful when you read old tutorials.
8- From Library window, under Objects, find Push Button and drag/drop it to the form. In the Attributes change the text for new button to Clear.
9- Hold the Control button and drag/drop to AppController in Document window. Select clearText.
9- Save and run a simulation of the interface (File/Simulate Interface).
10- Go back to Xcode, build and run. You should be able to type text and clear it with the button.

Now if you compare this with C#.NET, you'll see that Cocoa version is more complicated mainly because:
1- Xcode and Interface Builder are not integrated
2- In C#.NET, there is class automatically generated for you to control the form.
3- Adding a member variable for Text View and an event handler for Button are much more intuitive in C#.NET
4- You only add one line of code to the event handler to clear the text view.

To conclude, the IDE for Windows/.NET is clearly better. Cocoa does provide some basic default features that make standard tasks easier but when you get to real coding, it seems to be more complex and difficult to code. My next step is to do some 2D graphics programming. That's again one of the cases where OSX claims to have better built-in features, mostly Quartz functions. We'll see.

My #7 post will be a little late for the reason I explained at the beginning but don't worry,

I'LL BE BACK!

No comments:

Post a Comment