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!

 

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. :-)

 

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.

 

Mastering Xcode 4Well that’s that. The Xcode 4 book is finished and currently being printed (and prepared for digital sale in a number of formats as well). You can preorder it now if you like. See the official announcement for (un)specific dates.

Special thanks to the crew at Peachpit (Cliff, Myrna, Scout, Robyn, Kim, and the design team I didn’t get a chance to work with directly). Thanks to all my friends and colleagues for their support and to Matt for putting up with the whole thing. Thanks to Cyril and Colin for allowing me to use their work while writing the book. Finally, thanks to Duncan for getting me in touch with Cliff.

 

It’s been awhile since I’ve posted any new Cocoa stuff. Especially anything as widely loved as JLNDragEffectManager. Since I love all that positive attention and am sorely disappointed by the recent falloff of ego-sustaining limelight, I thought I’d solve yet another of the Cocoa world’s problems and give you a rather easy way of mimicking the “recessed list effect” found in Dictionary.app. I was reminded of the effect by this StackOverflow post today (thanks, Li Fumin, for reminding me I wanted to figure this out).

The Recessed Look in Dictionary.app

The Recessed Look in Dictionary.app

The effect I’m talking about is shown to the right. When you search for a word and there are multiple results, you get a list on the left that looks as if it’s recessed. It’s no simple shadow edge because, to achieve the desired visual effect, the top and bottom have to fade out, forming a visual depression.

How Does It Work?

This lovely effect requires subclassing three views (as far as I could tell to get it to work correctly). A NSTableView subclass provides the basic shadow edge. An NSView subclass provides the same edge but a fade at the top and bottom. An NSSplitView (set to Thin Divider mode) subclass draws the divider with the magic slightly-lighter-than-default color and the same top and bottom fade.

The “backing” view (the NSView subclass) has to provide the fade because the table view’s top and bottom edge move around when scrolled, which would take the fade with it were it responsible for this. The table view is sized in the backing view to leave an 11-pixel gap at the top and bottom to let the backing view’s fade show through. The backing view stays put and also provides a repeat of the shadow effect to account for the iOS-like elastic scrolling that was added in Lion. Since table views are happiest when they draw a background, this was a good design compromise.

It’s Not Perfect

It could be better. It doesn’t exactly match Apple’s flavor as I’ve fudged some things and don’t have enough time to polish it up more. You’re more than welcome to fork it on Github, make improvements, and send me a pull request.

How Do We Use It?

See the source page for details. Long story short: copy the three view subclasses (six source files in all) into your project. Open the example app’s MainMenu.xib and copy the split view and its contents into your project (you’ll probably want to replace the web view with something sensible). That’s all there is to it.

How’d You Get the Colors?

I use and rely on xScope (by Icon Factory) for such things. Well worth the money over the years.

Where Do I Get It?

Either the source page on my site or from Github. Liberal license (but I request attribution … you know … ego whoring and all). Enjoy!

 

 

I had written previously (twice) about missing debug symbols and strangeness related to compiler optimization in Xcode. I’d specifically mentioned per-file compiler flags. You may be wondering where they went in Xcode 4. “Ur flagz … let me show you them.”

The “old way” (Xcode 3 and lower) was per-file. That is, no matter the build target, the same source file would use the same per-file compiler flags. In Xcode 4, you have somewhat better control as you’re now allowed to set per-file flags per-target. That is, select your project in the Project Navigator, select the relevant target (you may have only one), then select the Build Phases tab. Expand the Compile Sources phase and viola! A Compiler Flags column lets you set each file’s flags for that target.

It would be nice to be able to further break it down into per-file-per-target-per-build-configuration so we can only apply -funroll-loops and -O3 to targets built for release. That’d save a lot of headaches when you’re suddenly jumping around wildly in the debugger when you enter a for loop.

 

Another quick Xcode debugging tip: If you experience “orange breakpoints” when debugging and have verified you’re in debug mode, and have cleaned and rebuilt your target to no avail, try disabling “Load Symbols Lazily” in Xcode’s Debugging preferences panel.

 

A brief tweet to Drew McCormack finally gave me my first Mac App Store idea. Read on for the great reveal.

The (iOS) App Store’s flashlight app market has already been saturated. Now with the iPhone 4′s built-in LED camera light, the paid updates for the new flashlight features have milked that market dry. So what’s my ground-breaking idea that will mirror the mobile market’s success? We think you’re going to love it. I mean I think you’re going to love it.

Ladies and gentlemen, meet Lamp.app.

The All New Lamp App

Lamp.app in Action

1.0 Features

  • Full-screen mode
  • Brightness control
  • Automatic power-save mode
  • Choice of colors (white shown)

Planned Features

  • In-app purchases for a variety of lamp shades (with thanks to @dunk for the idea)
  • Emergency Road Beacon (laptops only)
  • Clock and weather (additional in-app purchase)

Availability

Available soon from the Mac App Store for just $9.99, you lucky, lucky bastards!

Secret built-in tethering not included.


Note to fellow devs: Yes, I did reserve “Lamp” in the MAS. Just to be a dick :-)

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