I saw another StackOverflow post today that reminded me I needed to solve this problem once and for all: An easy-to-use table / outline view that fades at the top and bottom as it’s scrolled. Turns out I needed an NSScrollView instead. You can learn more (including how to get it for yourself) on its source page. Here’re a few examples of its configurability:

Happy coding!

 

Those who love and respect the special bonds we can form with animals – the bonds that show us that the term “people” is a bit too specific to a certain know-it-all species – can skip this. It’s not meant for you and won’t say anything you don’t already know. This is directed at those others.

Permit me to rant a moment. There are those who see our companion animals as things. Too stupid to know any better, to remember their past, to understand pain and loss. Then there are those who know better. Not because of some idiotic mystical nonsense, but because they’ve actually opened up their hearts and minds to a dog, a cat, or some other intelligent animal. That’s when they learned that, while no animals – a cat for example – are quite as smart as a human they’re damn sure not stupid. The smarter ones are … smarter. They remember things. They get sad and even vindictive. If you don’t think a cat can hold a grudge and then make a very clear point beyond “stupid animal” about it, you’re the one who is fooling yourself, not the cat owners.

The same goes for a dog. Hell even pig owners who’ve allowed a pig the same special place in their family as a cat or a dog can see an impressive amount of self-aware “person” in that creature. It’s a shame they’re so tasty I’m not a PETA member, I’m an omnivore, but I believe in treating all animals (even the ones we eat) with respect.

I address this post to those insensitive, vulgarly stupid assholes who close their eyes to reality and favor “conventional wisdom” – for whatever reason – about just what defines a “person” and whether a cat, dog, pig, horse, dolphin, chimpanzee, or whatever has a right to be treated, respected, and loved like a person.

For those of you who would tell me, in my current situation with a sick cat whom I’ve lived with and loved deeply for my entire adult life, that “she’s just a cat” and that I’m somehow being unreasonable with the depth of emotion I feel over her rapid decline and eventual loss, I have a few things to say to you.

First: Fuck you. Seriously.

Second: I feel very sorry for you (but still, fuck you) because you’re missing out on one of the most important lessons you can learn in this life.

Third: I never wish a beloved animal (*person*) in your life to die, but here’s what I do wish upon you: Against your will, a creature whose intelligence and personality you’ve dismissed, will worm his or her way into your heart. You’ll grow to truly recognize them for individual they are. Then you’ll be forced to be there for them when they age and eventually die. I hope that by this time your bond is so close, you wouldn’t dream of being impersonal … that you’d feel the responsibility toward your loved one that really is there – the deep-seeded need to be there for them, to make them comfortable, to worry over whether to let them go naturally or worse, to worry over when it’s time to end their lives for them.

In short: I wish you my fate. Not out of cruelty, but out of a hope that there’ll be one less hard-headed, closed-minded, soulless fuckwad out there because he or she went through a heart-breaking experience that taught them one fuck of a valuable lesson about love and commitment.

Even if it is “just a cat.”

 

November was a busy month for my career. Not only did I change jobs (again) but I had three separate speaking engagements.

CocoaHeads, DC

On November 2, I gave a whirlwind tour of Xcode 4 (highlights from my Xcode book) to the nice folks at the DC CocoaHeads meetup. Side note: LivingSocial has a great office space.

iDeveloper Live Podcast

I was also a guest on episodes 34 (November 21), and 35 (November 28) of the iDeveloper Live podcast. The hosts, Steve “Scotty” Scott and John Fox – graciously allowed me to blather on about (you guessed it) Xcode 4. Episode 34 was about its good side; episode 35 was a gripe-fest. I felt rather bad about spending nearly an hour complaining about a tool that is rather good, in spite of its faults. All month long, Scotty had been giving away e-book copies of Mastering Xcode 4.

Thanks to my hosts for the opportunity to speak and thanks to all those who listened patiently to my dimwitted jokes. :-)

 

A minor boast: it’s gratifying to see the hard work Dr. Roederer and I have done on SPICE is being put to good use. The paper has been cited* a number of times. This week I went back to work for Dr. Roederer full-time to continue improving SPICE and to plan and build yet another bioinformatics tool.

* I also just discovered Google Scholar. :-)

 

Conventional Cocoa wisdom holds that each window in an application should be in its own nib/xib file. The benefits are shorter launch times, better memory usage, and better Xcode project organization. Conventional wisdom is always right … right? We cynics know better. True wisdom is knowing when conventional wisdom is wrong.

I haven’t posted in awhile (especially anything Cocoa related) but the subject showed up on my radar again. What bothers me is this generalization: if you’re not (always) segregating your windows with nibs, you’re (always) doing it wrong. I have to take a stand. Blind adherence to generalizations will get you in trouble.

The Methodology

Let’s consider the approach. The basic idea is that every window in your app is placed into its own Interface Builder (nib) file. This coincidentally forces you to use one NSWindowController per window, which in turn forces you to keep that window’s UI management logic separate from other windows’ UI management and so on. For larger applications (which implies larger Xcode projects) this has performance and organizational benefits.

Note the term “basic idea” – this is where rote advice repeaters can fail their listeners. I’ll admit it: I make this mistake myself. If you repeat a bit of advice often enough, you become lazy. You carelessly overgeneralize. This can result in misguiding others. We’ll get to that part in a bit. For now, let’s have a bit more detail.

Performance

If you’re not familiar with the concept of “lazy loading” you’re doing yourself and your users a disservice. Lazy loading means only loading resources when the user’s actions demand the resource. That is, only load the UI that’s needed now. In the case of the “monolithic nib” – where the entirety of your application’s UI is in a single nib file – your application takes longer to launch and uses more memory whether it needs to or not because it’s loading everything. This is often unnecessary.

A favorite example is the preferences window. A user is unlikely to adjust the application’s preferences every time they use the application. It just doesn’t happen and we know this. Many apps have toolbar-driven, multi-pane preferences windows (another “is-it-really-necessary” discussion begging to be written). Does all that need to be loaded at launch time? No. It’s better that the preferences UI be loaded only when the user requests it for the first time.

Another example is the really complex application. Complex panels, such as Xcode’s Utility Area, can come with entire populations of sub-panels and may never be used during a session. If you’re any kind of sane, there’s at least one top-level NSViewController that manages such a panel but in reality, an extremely complex application may have view controllers for each sub-panel as well. For something as large and complex as Xcode, it’s a good idea not to load all of this unless the user asks for it.

All but the smallest, simplest of apps usually have at least one opportunity for lazy UI loading of a unit. The agreed-upon major unit is a window and its contents; a view is the minor unit. Anywhere you see a UI unit that may not be seen during a user’s session is an excellent opportunity to segregate and therefore to save time, memory, and even battery power. iPhone users will thank you for the latter.

In fact I’ll go a step further by saying anywhere you see an NSWindow and NSWindowController pair or an NSView and NSViewController pair that may not be used is an opportunity to optimize.

An opportunity. Remember the specificity of that word.

Organization

From the developer’s perspective, simply maintaining a large Xcode project offers its own set of challenges.

Good organization is more than just satisfying OCD. A well-organized project makes it easier to find things months or years down the road when you revisit a part of your app you haven’t needed to in awhile. Believe me, this long-time-no-see scenario happens often when you have more than one app. Or when your app is complex. Or when you’ve come back from vacation. Or when you finally got over being sick to death of even looking at that damn app.

Organization is especially important when working on a team or when you pass on the torch to another developer. This is similar to the need for readable, well-commented code. You can’t remain intimately familiar with every facet of your large project. Your future self (or your replacement) will thank you for making things easy to parse later.

Putting the preferences window in PreferencesWindow.xib (or whatever clear and concise naming convention you choose) makes it easy to find the related UI. Together with groups (the yellow folders in Xcode), the project is more easily navigable. You have a reasonable minimum of three files to maintain: PreferencesWindowController.h, PreferencesWindowController.m, and PreferencesWindow.xib. Put these in a group called “Preferences” and you can keep the group collapsed until you need to work on the preferences system. Put other preferences-specific source files there (like view/view-controller files if it gets really complicated) and you stay organized.

Zen and the Art of Xcode Project Organization.

Another organizational benefit is fault tolerance. Although it’s a less frequent occurrence these days, corrupted nibs have bitten nearly every Cocoa developer. Like the segmented hulls of modern ships, the puncturing of one segment shouldn’t sink the ship. Similarly, one corrupted nib in a well-segregated project causes less of a mess than that monolithic nib into which you stuffed the entire universe.

This is much less of an issue if you’re using a source code management system like Git or Subversion and make frequent, task-oriented commits. You are using source code management, aren’t you? Even so, there’s still risk of unnecessary loss of work if a nib is corrupted when you’re changing a lot of your UI at once. In the monolithic nib, all those changes are gone if the nib croaks; with multiple nibs, you only lose the work done in the corrupted nib. It’s a marginal benefit but you’ll be glad for it if the situation rears its ugly head.

The Exception

The point I’ve been coming to is this: it’s possible to take it all too far.

Consider a small utility app. It has one main window that’s always visible and a secondary window (let’s say a floating palette, despite their decreasing popularity). Neither window is particularly complex and the secondary window is likely to be invoked during each (possibly every) session. The use of multiple nibs here is ridiculous. I’ll tell you why.

The user launches the app to perform a task. The MainMenu.xib file is read and the UI is loaded. The task likely involves a utility palette. The app is user-friendly so the palette remembers its shown-or-not-shown state from the last session and needs to be loaded. Now there’s a second round-trip to the disk to read its nib file and load its UI.

If you know the utility application will never become the next Photoshop, your blind “future-proofing” is utterly pointless. You’ve increased your application’s load time and disk activity for nothing. You followed the “conventional wisdom” you heard summarized somewhere without considering why you were doing it and in this case it was the wrong thing to do.

You’ve also added more files to your Xcode project. Did it help? Did it make your small, simple project easier to navigate and to maintain? I’ll bet not. Interface builder helps you extract and segregate UI from a single nib; you’re on your own if you want to merge nibs. From an organizational standpoint, over-segregation can be a burden. Just navigating between several interrelated nib files can become cumbersome. It now involves tabs and assistants. It may soon involve satellite surveillance and an operations team. Think The Bourne Identity.

Conclusion

Is it all really necessary? For medium-to-large-complexity apps, you’re sure to benefit at least a little. For small projects, you might be hurting performance and maintainability. Remember the word “opportunity”? It’s not the same as “requirement”. Always consider the units of measurement (window/controller pairs and view/view-controller pairs) and the likelihood those units will be used in each session.

In short: prefer true wisdom to conventional wisdom and think before you segregate.

 

Ziplight IconA rather nice e-mail arrived in my Inbox this morning from a gentleman who used my Ziplight Spotlight plugin well past its prime. “Chris” writes:

…I noticed you’re the ziplight developer, so I just wanted to thank you for it, and share my story; since I suspect I’m the only man who used Ziplight on Snow Leopard.

I was searching for a solution to tagging comic files (just renamed zips) without using spotlight comments, and then I thought of a slightly ghetto method using file names. So I took ziplight and swapped in the UTI I needed.

Since I was a late comer to Lion, that act got me an extra 2 years of life out of Ziplight.

It makes me happy to see someone still had a use for it well after it became unnecessary. Old apps and plugins so often fade quietly into history…

 

I’ve been making a lot of personal posts lately. I have another. You might have noticed my presence online has been somewhat subdued lately. It’s no single reason; it’s a number of them altogether.

My sister lost her (very sweet) cat to cancer. My own cat had a lump that was removed – she’ll be fine (but she is an old lady and still has old lady issues). The problems didn’t stop at pets, though.

One of my sisters has been diagnosed with Multiple Sclerosis. She’s a mother of two in her thirties. It’s not mild but fortunately it’s not end-stage-severe. We’re all still reeling. Just a few months ago, her youngest daughter had a seizure . Looking back, it’d been going on awhile but this one was bad. She’s now on medication, probably until her adult years.

Another sister (mother of three) was very likely misdiagnosed with MS a few years ago but her latest doctor – who is angry at the previous “diagnosis” – is now thinking syringomyelia but a lot more testing is necessary. There are definitely cysts on her spine (thus the earlier diagnosis) and the kinds of problems that go with them. We’re still waiting to know more.

As if this wasn’t enough the sister I just mentioned has a fourteen-year-old son. He’d been having odd problems for quite some time now. I’ll skip the details, but it’s now confirmed: he has a form of lymphatic cancer. He’ll have a catheter inserted tomorrow so he can begin chemotherapy. At 14. Fortunately, this form has an 80% recovery chance (which I think is higher since he’s so young and it was caught so early).

But wait, there’s more. An uncle on my father’s side was just diagnosed with prostate cancer. It has progressed enough that it’s now in his bones. I don’t know much more than that.

A familiar problem we thought we’d solved popped up as well – Matt’s ongoing sleeping problems have resurfaced with a vengeance and it looks like it’s back to obstructive sleep apnea (for which he’d previously had a positive sleep study and painful operation to correct). We’re exploring next steps but for now, it’s back to the problems associated with lack of oxygen while sleeping many times per night.

How are we taking this all? Well, we’re all alternating between grieving and laughing together. It’s our way. I’m personally bouncing between optimistic and focused (throwing my energy into work) and depressed and crying. It’s a lot to deal with but that’s what’s going on with me right now.

Keep me in your thoughts and prayers (just because I’m areligious doesn’t mean I don’t appreciate the latter). A special thanks to those of you who’ve sent me words of support over the last few weeks as some of this came to light. Truly: thank you.

 

Back when I was a young, pimply geek, I trashed Apple like it was going out of style. Little did I know it would. Crapple. Crapintosh. MacIntrash. I’ve used them all. It wasn’t until 2000 (after falling in love with Linux) that I discovered a modern Unix with a unified UI. A Mac I liked. A Mac that ran Unix.

From that moment forward, I kicked my hobbyist-level programing dalliances into high gear to become, a decade later, a damn good Cocoa developer 100% devoted to the Apple ecosystem. 100% of my income is due to my Cocoa and Xcode knowledge and I’m much happier than I was as a network engineer – even as IT Manager.

Steve Jobs started something. Then he was booted out of it. It suffered. He came back. In less than 15 years, it rocketed to the top of many lists that matter. Steve’s leadership made my career and success possible. Would I have found it otherwise? Possibly – I’m a very driven person – but “possibly” didn’t happen. Steve and Apple did. So I am where I am now because of it.

Thanks, Steve, for positively affecting my life.

© 2011 Joshua NozziJoshua Nozzi is a Cocoa developer for hire.Suffusion theme by Sayontan Sinha