Aug 2011

Never on 9

I was listening to the Your Mac Life podcast from August 24 — and NetNewsWire came up. “That takes me back to OS 9!”

Just FYI, to the world (not that it’s earth-shattering information or anything): the first OS that NetNewsWire ran on was 10.1. It started life a Cocoa app, a Mac OS X app.

(I did write software back in the Mac Toolbox days, yes, but NetNewsWire was Cocoa from day one.)

Good Cocoa blog

I just ran across the Use Your Loaf blog. It’s good — a whole bunch of content, well-written and well-explained.

Thanking Steve Jobs

I wrote a thank-you to Steve Jobs on the Glassboard website for the company.

Writing a personal thank-you escapes me for now. Too hard. I’ve been a fan since I got my first Apple II Plus, 31 years ago, when I was just 12 years old. That’s a long time. My life wasn’t changed so much as defined, given a shape and a mission and a sense of humanity. How do you thank for something that big?

ReadWriteWeb quote

Glassboard got a nice write-up in ReadWriteWeb (one of my favorite sites). I love this line:

Sadly, listening meaningfully to other people will never be as popular as babbling about yourself or drooling

Glassboard released

You may remember that I started a new company. Now it’s a new company with a product: Glassboard.

It’s a free iPhone app, on the App Store now. There’s also an Android version and a Windows Phone version. (The Android version is by Nick Bradbury, creator of HomeSite, TopStyle, and FeedDemon.)

Glassboard is kind of like social networking, in that you share messages, comments, pictures, videos, and locations. The difference is that it’s completely private: what you share doesn’t end up appearing in Google searches.

You create a group (“boards,” the app calls them) and invite people. Only the people on a board can see what’s posted there. It’s like Vegas that way. (“What happens in Vegas...”)

And of course people can invite you to their boards, too.

Pretty simple idea, and you can imagine how it would be useful for anything from business deals to pictures of your kids. (Before you ask: we use SSL only, and data is encrypted in storage on the server. Our privacy policy goes into more detail.)

We started using it at work months ago, once we had just the bare basics working — and we haven’t looked back. It was obviously useful from day one. (And my email has gone way down, which is a nice side effect.)

Bonus: if you’re a developer, you should find Nick’s story on going from Delphi to Android interesting (even if you’re not an Android developer).

Also: if you check it out, and you’re not sure who to invite to a board, feel free to invite me using my company email. (First name plus company domain name.) Send me a picture of your cat or dog, or tell me a joke, or just say hi — whatever you feel like. :)

Less code, less effort

Here are a few things I’ve been doing lately to write better code, and less code, with less effort.

Synthesized instance variables

Adding a property is costly when you have to declare it three times: once as an instance variable, once (or twice) as a property, and once with @synthesize.

Last year I had tried synthesized instance variables, where you only have to declare it as a property and with @synthesized. I remember being disappointed because the synthesized variables didn’t show up in Xcode’s debugger.

Then I tried it again the other day, and the variables appeared. Somehow I’d missed the memo that it works now.

I promptly went through and deleted all the instance variables from my app. They’re now all synthesized.

Automatic Reference Counting (ARC)

For anyone who’s been writing Cocoa apps for a while, manual memory management is second nature. Me, I don’t even think about it. Errors are extremely rare (but they can happen).

I took a few hours the other day and converted my app over to ARC. That meant deleting a whole bunch of code: no more retains, releases, and autoreleases.

I also deleted a whole bunch of dealloc methods. (When I had to keep a dealloc method, it was just to remove the object as an observer.) If you think about it, dealloc was, in a way, yet a fourth place where you had to declare a property. (Once as ivar, once or twice as property, once using @synthesized, and once in dealloc. Crazy. That’s the kind of thing that makes programming a chore.)

Less work, less chance of error. ARC’s cool.

valueForKey on arrays

If you write code that works with a database or via web services, there’s a good chance you’re dealing with unique IDs of some kind, and there’s a good chance you need to get an array of those IDs sometimes.

The way I used to do this:

NSMutableArray *arrayOfIDs = [NSMutableArray array];
for (RSFoo *oneFoo in someArray)
   [arrayOfIDs addObject:oneFoo.uniqueID];

There’s an easier way:

NSArray *arrayOfIDs = [someArray valueForKey:@"uniqueID"];

This isn’t particularly new, but I used to always forget about it. (Obviously, it’s useful not just for unique IDs. I just mentioned that because it’s a common case for me.)

Configuring rather than coding

My app makes 25 or so different calls to our platform. I wrote this as one base class and 25-ish subclasses.

That’s not wrong, but it totally and completely sucks. It means 50 files to manage. It means creating two new files and coming up with a new class name every time I want to add a new call — and it means a new chance for errors and bugs.

What I noticed about these subclasses is that they only two do things:

  1. Configure the call before sending it. (Set the HTTP method, set the URL, add parameters to the right places.)

  2. Turn the result into an object. (Usually that means taking the result of the JSON parser and turning it into a model object.)

I’m in the middle of getting rid of all these subclasses. Instead, each API call is defined by a struct, and those structs all live in a single file.

const RSAPICallSpecifier kGBAPICallDownloadNotifications = {
   .httpMethod = kHTTPMethodGet,
   .path = "notifications/",
   .returnType = RSHTTPReturnTypeJSON,
   .returnedObjectClassName = kGBNotificationParserClassName,


I could have used a plist or something else. The point is that how-the-API-works is a form of data, and I can separate that from the code that talks to the server. That makes it easier to make changes and additions. It means less code to read and write and manage, and fewer chances of errors.

(For bonus points, our API description would be on the web in some parseable form, and I’ve have a script that downloads that data and then rebuilds those structs, and also alerts me to what’s changed. Not a new idea, no.)

Blocks and GCD

I don’t mind the formality of delegates and protocols — except that it does mean more typing. There are plenty of times when creating an API that takes a block will save a whole bunch of work and be just as clear, if not more clear. So I do.

I’m a big fan of NSOperationQueue, but it usually means creating a class, overriding the right methods, and so on. There are times when GCD will do instead. So I use that also.

Here’s how I split it up: I use NSOperationQueue when I have something somewhat long-running. I want to set priorities and dependencies, and I want to be able to monitor and potentially cancel operations. The main use is for downloading things: making calls to our server, downloading thumbnails and images, that kind of thing.

But I’ve slowly come around to seeing that there are cases where GCD is perfect for me. An example is rendering images — for instance, if I want to create an image with rounded corners and a drop shadow, I do it in the background via GCD. There’s no need to monitor these or be able to cancel them.


It may be my best friend. I toss in rendered images, text measurement calculations, strings that are expensive to calculate, etc.

I used to have all kinds of different caches, and now I use NSCache almost exclusively. (There are rare cases where I might use an NSMutableDictionary or NSMutableSet.)

It’s super-easy to use — like an NSMutableDictionary, it responds to objectForKey: and setObject:forKey:.

Particularly cool is that an NSCache handles removing items itself. I don’t have to think about it. It means fewer things I need to do when getting a memory-warning message.

Xcode 4 text snippets

I was bummed at first to lose the Xcode scripts menu. (My hope is that I can replace the features I miss via AppleScript and FastScripts.)

But having the text snippets is way better than the previous system for adding completions. Drag some text in, give it scope, title, and completion shortcut, and you’re good. It works, and it’s worth doing.

(There are a few things I wish for, though. User-entered snippets should be at the top, not the bottom, since they’re probably more important. And it’s silly that to remind myself of a completion shortcut I have to double-click the item and then click Edit. It should just be part of the display in the table. [I’m a developer. Please don’t make me click so much.])

Some things I still wish for

I wish I didn’t have to use @synthesized. I’d love to be able to declare a property exactly once.

I wish Xcode’s autocomplete would still work before I’ve imported the header file for a class that it totally knows about. It means I have to stop my typing, go to the top of the file, import the right .h file, then try to find my way back to where I was. (The back command should work after a cmd-upArrow.)

I wish Xcode would just add import statements for me when it’s unambiguous. (I’d wish away header files and imports entirely if I could.)

I wish I didn’t have to delete the DerivedData folder when things go wrong. I wish I didn’t have to delete xcuserdata when Xcode stops being able to keep up with my typing (on an 8-core Mac Pro).

I wish I could type someArray[0] and have it mean [someArray objectAtIndex:0]. Similarly, I wish I could type someDictionary['someKey'] = someValue.

I wish dot notation worked all the way through, as in someView.frame.size.height = whatever.

I could go on and on. Which is just to say that things are getting better — we’re able to do more with less work — but there’s always room for improvement. Gives me something to look forward to.