3 Essential Concepts for learning Cocoa/Objective-C
This post assumes that you know a bit about object oriented programming and one or two other object oriented languages.
One of the best ways of learning a new programming language is to look at code samples. And usually, you'll find that the structural concepts you've learned from other languages apply to the new language in such a way that you only really have to make a few syntax and naming translations and you're there. This is mainly true when learning to develop in Cocoa/Objective-C, but the more unique concepts it does use (and that the code samples often assume you know), can make the learning process a bit trickier. So, without further ado, I'm going to go over some of those concepts that turned into "aha!" moments for me and made the code samples I was looking at seem much clearer...
1. Categories, categories, categories!
Please picture a sweaty Steve Ballmer yelling this over and over and over at you. It's such a simple concept, but it's rare enough in other programming languages and used so heavily by Apple that to not know it could actually lead you towards a complete nervous breakdown while learning Cocoa/Objective-C (see above reference to Steve Ballmer). So, what's a category?
@interface NSString (MyCategory)
- (BOOL) someNewMethodThatReturnsYESorNO;
@end
Provided that you give an implementation for someNewMethodThatReturnsYESorNO, you can now call it on any NSString object. It's like re-opening a class in Ruby. As far as I know, Java doesn't have an equivalent (in Java, you'd need to subclass String and then change all of your references to create YourVersionOfString instead of just String). So using Categories for Objective-C can be quite useful for adding convenience methods onto base classes without having to change a bunch of class references (and also make it easier to shoot yourself in the foot with conflicting implementations from competing categories). But why would this be essential when learning Cocoa/Objective-C?
Enter "informal protocols". Now, current (10.6) Apple frameworks have replaced a lot of old school protocol definitions with the newer Objective-C 2.0 style @protocol syntax, but there is still a lot of sample code out there with stuff like this (taken from the NSWindow.h header of the 10.5 SDK – check out the 10.6 SDK for the @protocol version):
@interface NSObject (NSWindowDelegate)
- (BOOL) windowShouldClose:(id)sender;
@end
And Cocoa uses delegates A LOT. If you go through the various tutorials out there without understanding what a delegate really is, things will seem a bit magical. Just define this method on Object X, set it as a delegate for Object Y, and voila! Instant drag and drop! Or something like that. But this is really just a very general way to define an interface that any object can implement. And whenever you see something like the above in a header file, it suggests that you can change the behaviour of the class by adding the "delegate" methods to one of your classes and then setting that as the delegate class of the object you're looking at.
2. Bindings
Another thing you'll see a lot of in the tutorials floating around out there is "now bind your new text field to the someValue property of the selection of your NSArrayController and you're done!" Huh? This is all wonderful if what you're trying to do never falls that far from what the tutorial is showing you, but how many times does that actually happen?
Well, first of all, believe it or not, you won't often find yourself needing more than an NSObjectController, NSArrayController, or NSTreeController, and the closer you stick to using these, the better off you'll be in the long run. Basically, ask yourself if you're going to be working with a single value, a list of values, or a hierarchy of values, and then choose the corresponding controller in Interface Builder to bridge the gap. You bind the controller to a property of some object in your code and then you bind the interface element to the controller. The controller then mediates between the GUI and all the ugly internals of your application.
But how do I tell the controller that my object's value has changed so that it can then update the GUI component? Well, you don't really have to, as long as you've followed all of Apple's key-value coding admonitions (i.e. made sure that your properties are Key Value Observing Compliant). This gets done by default when you use @property declarations to define the object properties you're binding to and when you use @synthesize or @dynamic to generate the getter and setter methods in your object implementation. Really, all this does is make sure that you call willChangeValueForKey: before changing the actual property value and didChangeValueForKey: after. It's these methods that inform the controller that it needs to update the GUI component. But as long as you're key value observing compliant, you don't really have to know that.
Note that, until you "get" working with bindings, you'll probably find the use of Interface Builder very frustrating. "Just show me how to set this stuff up without IB and I'll do it by hand!" Unless you've used the Mediator pattern at some other point and recognize that this is that same pattern under a different name, and that the extra work you go through to keep your GUI and your data model in sync via this pattern is more than made up for by the time you'll save keeping multiple components in sync or switching GUI components in and out.
3. Responder Chains
There's this thing called a First Responder that you'll see when you create an interface builder file (aka XIB or NIB). And you'll often run into tutorials telling you to hook a menu item or a button up to the "First Responder" object in your interface builder file and then define a method somewhere else deep in your code and you'll find that somehow that method gets called when you click the menu item even though you didn't make this connection explicitly. More magic?
Well, as usual, what looks like magic is something pretty simple if you look closer. Check out Apple's Event Handling Guide for a more in depth explanation (particularly the "Responder Chain for Action Messages" section). But basically, what's happening is that, by default, the "first responder" is the GUI element that either has keyboard focus or is being operated on via the mouse, and when you click the menu item, the Cocoa framework is going to check if you've got the appropriate method defined on the implementation of that GUI element. It might also check that element's delegate if it has one. Then it checks the window object, then the window's delegate, then the application object, then the application's delegate, basically working its way up through successive containers of the object where the event actually occurred. Defining the necessary method at any point along that chain allows that particular object to handle it.
This can be made even more interesting when you use the setNextResponder: method of any NSResponder in the chain. Using this method, you can effectively insert your own objects into the chain to help make your code more intuitive.
Conclusion
This is by no means meant to be an exhaustive description of categories, bindings, and responder chains. Books devote full chapters to concepts like these. However, if you're at the point where you just want enough understanding to make some of the Cocoa/Objective-C code examples you'll see seem less like Voodoo magic and more like what you see in other languages and frameworks, I hope this provided a bit of enlightenment. As with anything else, it'll always be imperfect, so if you have questions, comments, or corrections, please let me know, and I'll update it accordingly.