I originally thought that I would be postponing my first blog post about Cocoa programming on the Mac for .NET developers until after Leopard came out. However, since I've had trouble downloading Leopard myself, I couldn't resist the temptation and I started writing some code in Xcode on Mac OS X Tiger.
Disclaimer: I am not intending to prove that Cocoa programming is better or worse than .NET Programming. I am merely exploring alternative means of development and journaling my progress with respect to a very .NET-heavy audience.
I've had 13 years of professional programming experience, and I've had another 10 years of hobbyist development experience before that. So, needless to say, I figured I could jump into Xcode and be rollin' in no time. Unfortunately this is where the men are separated from the boys, because Xcode and Interface Builder are actually easier to use for people who have not had any exposure to Visual Studio. Some Apple folks refer to people without Visual Studio experience as "untainted". Anyway, I ran into a stumbling block early on that I'm sure a lot of died-in-the-wool Microsofties will run into.
I tried to create the stereotypical "Hello World" application. I dragged a button onto a form and then I figured, "What the hell, this ought to work", so I double-clicked the button and was ready to try and figure out how to get a message box to come up. Much to my chagrin, all I did was pull up the properties inspector for the button.
My first reaction was to drop Xcode and go back to Visual Studio where I felt comfortable. You know how, even though something might actually smell really, really bad, the fact that you're familiar with it and might even call it home makes it endearing? The same is true of a development tool. Regardless of whether your tool is good or bad, the fact that its the tool you've been using for years makes it feel comfortable and familiar, like a security blanket.
I took a step back and tried to figure out what the hell was going on. After a few minutes, I realized that Xcode was actually doing a really, really, really good thing. The vast majority of problems that arise from a poor separation of concerns between the GUI and the underlying code, model, and controller (if you even have such constructs in your app!) stem from the fact that you can double-click a button and immediately start writing code without thinking about the consequences of such a thing.
The NIB (stands for NeXTStep Interface Builder) file is a loosely coupled, standalone, user interface definition. It wouldn't make sense to double-click a button and immediately be taken to a code-behind. Instead, you have to create a controller class, and then ctrl-drag from the button to the controller and then pick the outlet you're going to use (something like click: or calculate:). To me, as a huge fan of the MVC pattern, this makes perfect sense. And it seems so elegant in its simplicity, and so incredibly cool in the fact that it is truly enforcing good design simply by the way the IDE works.
So to get a handle on how Xcode wants me to implement the MVC pattern, I created a new application called Currency Converter, which is one of the samples in the Apple developer documentation that includes a full walkthrough tutorial (awesome tutorial, by the way!). Here's a screenshot of the GUI that I created:
There is a model class called Converter that contains the data underneath the form. There is a controller responsible for maintaining the interaction with the user that is contained within a class called ConverterController, and finally there is the view that is wrapped up neatly inside the NIB file.
Here's the code for the model object (Converter):
#import "Converter.h"
@implementation Converter
- (float)convertCurrency:(float)currency atRate:(float)rate {
return currency * rate;
}
@end
And here's the code in the controller (ConverterController):
#import "ConverterController.h"
@implementation ConverterController
- (IBAction)convert:(id)sender
{
float rate, currency, amount;
currency = [dollarField floatValue];
rate = [rateField floatValue];
amount = [converter convertCurrency:currency atRate:rate];
[amountField setFloatValue:amount];
[rateField selectText:self];
}
@end
What the controller's convert: method (I think they call it something other than a method in Cocoa) is doing is reading the currency and rate fields by sending the floatValue message to the dollarField and rateField outlets (created visually in Interface Builder) to get the current value from the text boxes. Next, the amount is set to the value of the convertCurrency:atRate method. Finally, the amountField text box is given the float value that is the result of the operation, and the ratefield gets focus after the operation.
This is pretty much the most basic example of functionality that you can get in a Cocoa application. For me, it was pretty eye-opening. I am used to right-clicking my Visual Studio 200x project and adding elements to the project. Its fast, its easy, and it keeps everything in a single, easy-to-find location. Here's the rub - keeping things in a single location like VS 200x does might not be the best thing. From my years of experience with VS, I almost always create project sub-folders, and I go way out of my way to enforce separation of concerns and try and create a M-V-C pattern even in situations where .NET does not appreciate that pattern very much (e.g. ASP.NET applications).
I'm hoping that the next application I post about will be more complex than the SDK sample I posted about here. The point I want to make here is that if you are a .NET developer with good discipline and respect for patterns like MVC, then you will find the transition to Objective-C and Cocoa easier than if you have fallen into the "VB" (no offfense) trap of storing all your code and business logic behind button clicks and other interface elements - creating a tightly coupled mass of spaghetti code.
tags: mac osx cocoa objectivec programming
links: digg this del.icio.us technorati reddit