Cocoa programming

What's a good tutorial on writing native, modern OSX programs? I figured I'd start by porting Dali Clock since that's both pretty simple and somewhat ironic.

I gather that use of the XCode interface builder and stuff is pretty much mandatory?

I found Apple's "Currency Converter" tutorial, but I find it kind of opaque. Like, how do I cause a window to appear when the Preferences menu item is selected? Where do I store my settings? Stuff like that.

Update: Online resources greatly preferred to paper books. I gather that this "dead tree" medium is still popular, but I find it really awkward for things like this.

Tags: , , , , ,

40 Responses:

  1. rexpop says:

    Try this book.

    There are three tutorials of varying complexity. It's a little bit dated, and doesn't cover the latest bells and whistles of the Cocoa framework, but gives you the basics. The other O'Reilly OS X programming book:

    Is decent enough as well. Also:

    Has a bunch tutorials that might help.

  2. "Cocoa Programming for Mac OS X" is a very good tree killing reference. It covers both the points you mention. The one thing against it is that it's Cocoa-only, and more focused on applications than graphics hacks.

  3. semiclever says:

    Not exactly relevant, but perhaps for the future:

    disclaimer: I stumbled across this a while ago but haven't gotten a chance to poke at it so I can't warrant its merchantability or fitness for any purpose.

    • duskwuff says:

      OpenGL screensavers are dead easy to port.

      Witness. (Source code only; compile it yourself.)

      Been ported before, but it's a good example. The hardest part of an OpenGL saver port is the preferences UI, which I've totally left out here because there weren't really any interesting options anyway.

      • taffer says:

        Bah, the UI stuff is easy. ;-)

        I tried porting GLMatrix, too, but got confused by the texture hackery going on inside. I'm not much of an OpenGL programmer.

        • jwz says:

          The thing to do is to write something that creates Cocoa dialogs based on xscreensaver/hacks/config/*.xml... Like, a perl script that emitted a .nib file or something?

          • duskwuff says:

            Or a bit of NSView hackery that reads the XML and generates the controls on-the-fly. Yes, you can just instantiate an NSControl at runtime, set all the values appropriately, and stick it into the window.

        • duskwuff says:

          Bah, the UI stuff is easy. ;-)

          Then give me a UI for the few possible settings in noof (move speed range, rotate speed range, color shift speed, fill opacity, shape count), and show me when you're done?

          (The original actually only had one setting, for frame rate, but surely you can do better!)

          • Also, if you have time, I'd like a pony.

          • taffer says:

            I was doing them with the exposed controls in the original X11 version, which was even easier.

            Sadly for you, I'm lazy and have been playing City of Heroes in my spare time instead of doing something useful. ;-) But seriously, a couple sliders, some check boxes, etc. is easy stuff with IB. It'll take more time to make it look decent and organized than it will to hook up the code.

  4. jarodrussell says:

    What about Safari? Or does that still fall under the "dead wood" category?

  5. ghosthacked says:

    Have you looked at tutorials that come with xcode? they're in /Developer/Documentation or something like that.

  6. duskwuff says:

    Better yet, if you're looking for documentation/examples/etc, check out the ADC Reference Library, which comes with the machine. (You may have to copy and paste the second link if your browser doesn't allow file:// links from untrusted sources.)

  7. Unrelated: Thank you for making your PalmDaliClock available as a .prec instead of a zip archive. Palm devices sometimes have internet, but rarely (never?) have anything capable of installing an app hidden in a zip file.

    • waider says:

      There's a thing called ZBoxZ which purports to do this. Since I don't have an intarweb-enabled Palm I can't tell you if it actually works or not.

  8. hafnir says:

    XCode is quickly becoming mandatory, yes. We're getting away with CodeWarrior still, but it's hurting more and more and more. XCode used to be severely slow but I hear it's been getting better and better.

    • spikenheimer says:

      wasnt xcode supposed to allow compilation across multiple xcode machines?

      • hafnir says:

        I also heard that, but I don't know where they went with that.

        • amcmillan says:

          1) Open Xcode
          2) Open Preferences
          3) Select "Distributed Builds"
          4) Tick "Share my computer for building with {high|medium|low} priority" and/or "Distribute builds to {all computers|trusted computers only}"
          5) Repeat on each Mac
          6) ???
          7) Profit!!!

          • legolas says:

            7) Cry as your app doesn't work in a non-reproducable way because one machine has a slightly different version of osx/xcode/gcc/the headers/...

  9. jfpoole says:

    CocoaDev is pretty nifty. They've got some introductory material, but I've found the site more useful since I've wrapped my head around the basics of Cocoa.

    Cocoa Programming for Mac OS X is a great introduction to Cocoa programming, but it is made from dead trees. It's the book I read when I was learning Cocoa, and it worked well for me. I hardly refer to it anymore, though, since it's more tutorial than reference.

  10. keithkml says:

    How many trees do you think you're killing every for every kilowatt of power your computer uses?

    • jwz says:

      How many non-sequiteurs had to die to create your comment?

    • Where do you live where they have wood-burning power plants? Considering that most of our power comes from fossil fuels that are burned into carbon dioxide and water, and also contribute to global warming, using our computers is pretty good for the trees!

      • Modern day trees, yes, but who is thinking about the Mesozoic trees that died so that we can have our fossil fuels today? Where is their due?

        [heavy sarcasm, for those who will undoubtedly fail to get this]

      • You could argue that forests get destroyed for coal mining, and that forests get drowned for hydro, and that any fossil fuel-based plant is going to contribute to acid rain, which decimates forests.

        But if they're not going to evolve to hunt and kill us first, I see no reason to argue.

        • drbrain says:

          No, coal mines do attack and kill humans.

          In the Carbonado/Wilkeson area of Washington methane pockets trapped in the coal layer would cause pressure explosions that would kill the miners. Eventually they had to shut down the mine because of it.

          Not to mention that you've got highly explosive methane gas forming huge yellow clouds.

  11. duskwuff says:

    Oh, and preferences are handled by NSUserDefaults, unless you're working on a screensaver (which have their own defaults system, for reasons known only to them).

    • taffer says:

      The docs say it's because of the way plug-ins get loaded, but they don't really elaborate on what would be going wrong...

  12. danomite55 says:

    I found Apple's "Currency Converter" tutorial, but I find it kind of opaque. Like, how do I cause a window to appear when the Preferences menu item is selected? Where do I store my settings? Stuff like that.

    First, you would want to create a controller object. In Interface Builder, go into the Classes tab, search for NSWindowController, control-click (or right-click) on NSWindowController, and choose "Subclass NSWindowController". Give it a name (eg JwzController), and then right-click on your custom class, choosing "Create files for JwzController", and then right-click once again to "Instaniate JwzController".

    Now, create the window you want to display. Make sure your palettes window is open by going to Tools, Palettes, Show Palettes. Find the Windows, and drag a window to your Instances pane.

    In your header file for JwzController, you can define something like:

    IBOutlet NSWindow *myNewWindow;

    Back in Interface Builder, you can browse the class tree back to your JwzController, right click, and choose "Read JwzController.h". It should pick up your "outlet". Now you need to connect the window to the instance of the controller. Switch the tab to "Instances". Hold down the Control key, and drag a line from the JwzController instance to the Window instance you created earlier. It should pop-up a window of outlets, and then you would just choose the "myNewWindow" outlet, and click "Connect".

    Now from your controller class, you have an instance of myNewWindow which you can manipulate programatically. You can set up similar outlets/connections for other parts of the interface, setup actions that will get triggered when buttons are clicked, etc. Obviously, I'm skipping over lots of stuff here, but the currency calculator example should give you a basic overview of creating such connections and actions. The build in documentation to Xcode is generally pretty good, though there are some concepts that I had trouble learning just from that documentation...

  13. danomite55 says:

    Oh, and lastly, subscribe yourself to the cocoa-dev list. It has a moderately high volume of messages per day, so I would use a Gmail or similar account if you don't want to be bugged that there are new messages all day. I have found the list to be extremely helpful when I'm unable to figure something out.

  14. fdaapproved says:

    For basic stuff macdevcenter and . The former is a bit more dated, but also generally better since they have editors and stuff. For slightly more advanced (read: Assumes that you may have heard of this 'programming' the kids are doing these days) there's Andrew Stone's Cocoa Files. After you learn about Bindings and then decide you want to kick that engineer in the nuts there's this to help you get your preferences screen working. Finally, cocoa-dev is archived (and searchable) here and you probably also want something like AppKiDo for browsing the developer docs. I dunno, doing it inside Xcode just pisses me off for some reason.

    You don't precisely need Xcode, but setting up the Makefiles yourself is painful enough that most people don't bother not using it. The usual way is to set up a skeleton app structure with all the resources in place so you can just clone that and then copy the executable into place during the build. Back in Xcode, there is a CLI build tool called 'xcodebuild' that makes building projects easy, but the Xcode file formats are pretty opaque despite just being giant dictionaries.

    Interface Builder OTOH is harder to avoid. NIB files are basically serialized objects so they're more like Smalltalk images or something than anything else. For the most part, this is handy since you can just whack 'em into memory and objects get instantiated and hooked up and whatnot. Unfortunately it also means that there's not really any way to automate their generation. It also makes fans of Tk sad because they don't have to spend half their lives screwing around with layout packing. For people who dig on Java-style layout managers and XML there's GNUStep Renaissance, but I don't know the status of the project. I gather that it runs under OS X, but I also like my controls where I put them so I don't care.

    Oh, and in answer to the window visibility question:

    Define an action for showPreferences in your controller (either by editing the controller object in Interface Builder, which annoys me for some reason or adding the following to your header and reloading it into Interface Builder):

    - (IBAction)showPreferences:(id)sender;

    In the function body

    - (IBAction)showPreferences: (id)sender {
    [window makeKeyAndOrderFront:self];

    Then, in interface builder hook the Preferences menu item to the showPreferences: action by ctrl-click-n-drag to the controller object (for something like that you usually just instantiate it in the NIB directly). Make sure the window outlet is hooked up in the controller by similar means. I don't remember off hand if the Preferences item is normally hooked up to a different action. In that case you should override that one instead of making a new action.

    Have fun.

  15. bitpuddle says:

    I think many of the good online resources have been mentioned. Also take a look at Karelia's stuff, the tutorials at Stepwise, and CocoaDeav.