Cocoaphony

Stop mutating, evolve

Learning Cocoa With Other Backgrounds

From a StackOverflow posting.

When I teach Cocoa, I always ask the class what their background is in. This generally tells me what they need to unlearn before they’re ready for Cocoa. Here are some of the things I’ve found that different groups need to unlearn.

For C++ developers:

  • Naming. Correct naming is critical in Objective-C. The compiler will not save you. Learn the naming conventions and follow them.

  • Dot notation. Dot notation is pleasant to type for experienced Cocoa developers, but extremely confusing to new developers. Dot notation does not mean “get or set the ivar of the object.” Dot notation means “pass the message -foo or -setFoo: to the object.” These two statements seem very similar, but are in fact radically different. Most importantly, foo and self.foo are not the same thing, though often they may appear to be the same thing. Assigning to the latter will generally retain the object, while the former will not.

  • Following up on dot notation, accessors are not mandatory in ObjC, but should be. Always, always use them (except in the accessors themselves of course, and in -dealloc). Do not access your ivars directly. Not even if you see sample code doing it.

  • The reason for all of the last three issues is memory management. If you will follow these last three rules, then your memory management will be easy and you will have very few problems. If you do not, and C++ folks often are very bad about this because C++ has such sloppy naming conventions, then you will have terrible memory management problems. 2012 Update: Note that with ARC, memory management has become much simpler, but my recommendations haven’t changed.

  • Objective-C can use C++. I recommend strongly, however, that you keep your C++ and Objective-C separate, and have only a thin translation layer in Objective-C++. Learn to use NSArray rather than vector, etc.

  • C++ developers often get confused about how Singletons are used in ObjC. If you understand the full, correct Singleton pattern, then you need to understand that ObjC generally doesn’t use it. It’s ok to have a static in ObjC that holds the “shared instance” and that you never free. OS X (phone and Mac) will recover the memory for you at program termination. It’s ok to have a “singleton” that can actually have multiple instances (NSNotificationCenter and many other objects allow this). There is seldom reason to really ensure that you are the one and only instance of the object (if you’re overriding -release, stop, even if you found the code to do it on Apple’s site). “Singletons” are generally just an instance that happens to be stored in a static and is returned when you asked for the “sharedController” or “sharedFoo” or whatever.

  • Threading is somewhat rare in Cocoa. Most things are done on the Run Loop, which is cooperative multi-tasking. You get asked something, you respond as quick as you can, all on one thread. 2012 Update: Cocoa programs are becoming more multi-threaded, but you should still very seldom create your own threads. You should use dispatch or operation queues and let the OS handle threads for you. Creating an operation block is a different pattern than creating a worker thread. You should very seldom create worker threads. Operations are much more scalable, generally faster, easier to code, and have fewer inter-thread interactions if written correctly.

For C developers:

  • I push C developers to stay away from Core Foundation (things that start CF). Core Foundation is very useful, but it’s too easy to let it become a crutch to avoid actually learning Cocoa. It’s better to first learn Cocoa in ObjC, and then come back and use Core Foundation when you need to.

  • Do not be afraid of long descriptive names. Get used to them. Love them.

  • Embrace objects. Even the C-based Core Foundation is basically object oriented in C syntax.

  • Don’t forget your C. A lot of Objective-C is done in straight-up C. It’s just C, really. C++ isn’t, but Objective-C really, really is just C.

  • Objective-C is really C, but Cocoa isn’t. Cocoa is Smalltalk. And so you really need to study the Model-View-Controller paradigm and live it every day.

Java/C#:

  • Java developers seem to have the hardest time with dot notation. I often just flat-out ban dot notation for former Java developers. Don’t use foo.bar, just use [foo bar] and [foo setBar:baz]. You will save yourself a lot of headaches. A Java background just seems to make it much harder to break the idea that dot notation is really a method call and nothing else.

  • Even more than C++ developers, I have to teach Java developers that they aren’t going to spawn threads for things. Use the run loop, and do thing asynchronously with callbacks. As a beginner, you may never need to spawn a thread. I write a lot of complex code, and still only spawn maybe a couple of ObjC threads in a major program. 2012 Update: See comments in C++ section about threads. Dispatch and operation queues are much more powerful than manual threading.

  • C# developers (and Windows developers in general) have trouble with Interface Builder. When you create a button in Visual Studio, it writes a bunch of code for you. IB does not write code. IB serializes an object. A NIB is just an object archive. At run time, the NIB is read, and the objects are deserialized.

  • Objective-C does not subclass a lot. It uses helper objects (delegation, datasources). If you have a special window that can’t be closed except in certain circumstances, you don’t subclass NSWindow (you almost never subclass NSWindow for anything). You assign a delegate to the NSWindow instance, and when it wants to close, it asks its delegate -windowShouldClose:.

  • .NET has lots of objects that do similar things in different ways, and each time a new rev comes along, they give you a new set of objects that do those same things in new ways. .NET objects tend to be really smart with lots of little fiddle knobs to configure them. Cocoa objects are dumb, and that’s why I love them so much. A table view in Cocoa doesn’t know anything about querying SQL servers. A table view knows how to draw a table. It asks its datasource for what that data should be, and it asks every time it gets ready to draw a cell. It asks its delegate how tall each rows should be and whether a given row may be selected, just at the moment it needs the information. This is backwards of how .NET generally does things.

And that leads to my biggest point for developers coming from anywhere that isn’t Smalltalk:

  • It isn’t about you. It isn’t about your code. And it isn’t about your code doing this or that. It’s first about the user and responding to the user. It’s second about your code responding to the framework. You don’t usually tell the framework what to do. It asks you for things when it needs something. You sit and wait for it to talk to you. You’re not in charge. You don’t control the runloop; it controls you. You register to be told when things happen, and you indicate that you’re the object who knows something about something (data for a table for instance). And then you let go, and let Cocoa do the rest. It’s a very different world. I like it very much.