Archive for October, 2003

NSString+Templating Revisited

Tuesday, October 28th, 2003

My NSString+Templating category continues to evolve, so here are a few notes for those who care:

  • First, and most importantly, the incredibly knowledgeable and always helpful Scott Anguish pointed me to nice solution for one of the problems I had mentioned in a previous post: the need to provide “pre-processing” of a field’s text before it is put into the template.

    Scott’s solution takes advantage of yet another key-value coding feature I hadn’t noticed: the valueForKeyPath: method. The difference between this and the more commonly used valueForKey: method is sort of difficult to explain, but basically, it allows you to chain keys together such that the value of one key becomes the object from which the value of another key is derived.

    The key path is represented using a dot notation. For example, suppose we have a “Car” object, and it has a field called “engine” (an object of type “Engine”), which in turn has a field called “type” (which is just an NSString). From a Car model object, the engine type would be accessible using the following code:

    [theCar valueForKeyPath: @"engine.type"];

    As Scott suggests, we can leverage this technique to provide the “pre-processing” I was previously looking for. The trick is to put whatever formatting methods we need into our NSString category. Then, from the template, we can take whatever string output we get from a field and run it through our formatter (which is now a method of NSString) like so:

    <$name.stringByEscapingQuotes/>

    I really like this solution because it actually enables the template designer to specify formatted or unformatted output simply by choosing whether or not to chain the formatter onto the end of the key.

    The posted code has been updated to use valueForKeyPath: instead of valueForKey:, and the category now also contains several sample formatting methods (including one to escape quotes).

  • Now that Panther is out, I’m posting an Xcode project containing both the category itself and a snazzy little app I whipped up to demonstrate its usage. Download it here:

    - TemplateTest.dmg (30k)

    For those not using Panther/Xcode, I’m also still distributing the code by itself:

    - NSString+Templating.dmg (9k)

  • My previous distributions were inadvertently marked as governed by the Creative Commons Attribution-NonCommercial License. This was a mistake—I have no problem with NSString+Templating being used in commercial applications. The new version has been switched to the plain old Attribution License.

In the Ghetto

Sunday, October 26th, 2003

This morning Chuqui linked to what has to be one of the most ridiculous things I’ve read on a weblog in a long time: Tribe.net poobah Marc Canter’s derisive assertion that Mac users (and developers) are in a “ghetto.”

Now, never mind the obvious contradiction in Canter’s argument: he starts his post as a somewhat haughty defender of the “cross browser, multiplatform” world only to later reveal that he’s really only interested in what one browser and platform (Internet Explorer and Windows) can do. And forget about his misplaced pity for apps like NetNewsWire, which only shows Canter’s ignorance of the vibrant Mac indie scene (which I have experienced firsthand as the developer of an indie app). And, finally, ignore your outrage at the logical end of his argument, which is that no matter how useful or time saving or life-enhancing inventions by Apple or its indie developers are for Mac users, it’s all for naught since if it doesn’t happen on Windows, it doesn’t matter (and he’s not just talking about browser stuff here—he includes “digital lifestyle” in his list). All of that is annoying, to be sure, but not exactly unique and worthy of rebuttal in itself.

What really made me want to spend my valuable time writing a response to Canter’s post was not so much a fault in his argument as a fault in his language. By resorting to a loaded word like “ghetto” to make his point, Canter commits what is, in my opinion, one of the worst linguistic sins of modern politics—a tendency described by George Orwell in his essay “Politics and the English Language.” As Orwell writes, using the broad misapplication of the term “fascism” as an example:

The word Fascism has now no meaning except in so far as it signifies “something not desirable.”…Words of this kind are often used in a consciously dishonest way. That is, the person who uses them has his own private definition, but allows his hearer to think he means something quite different.

The use of the term “ghetto” here is no different. The word has several legitimate meanings—all of which call to mind negative things like racism, oppression, captivity, and (yes) fascism—but none, realistically, that should encompass computer users and developers who are loyal to a particular platform because they genuinely prefer it. Writers who use language so imprecisely are taking advantage of the modern “devaluation” of such words in an attempt to taint their target with long-standing negative associations.

This sort of imprecision is often an effective smokescreen that hides the essential weakness of the writer’s actual argument by confusing the issue. After all, who wants to be accused of being in a ghetto? Fortunately, that’s not much of an issue in this case, since that is by no means what the Mac platform is.

Night of the Living Panther

Friday, October 24th, 2003

Tremble, O unsuspecting public, for, as my cute widdle stuffed Panther and I would like to remind you, the great and terrible Night of the Panther is at hand!

Stuffed Panther

Personally, I’m hoping to escape the dread beast’s wrath by spending the evening with Jonas, Courtney and other South Bay Bloggers at the Valley Fair Apple Store and its environs. If you’re in the ‘hood, and want to say hello, we’ll be the ones with the PowerBooks. Oh, wait…

NSString+Templating Addendum

Thursday, October 23rd, 2003

A few additional notes on my NSString+Templating category:

  • As both Michael Tsai and Scott Anguish have pointed out, my assertion that primitive types work with the “%@” format string is a bit off (OK, it’s completely wrong!). “%@” is only for objects (it uses an object’s “description” method, which is a lot like Java’s “toString()” if you’re familiar with that), and it definitely doesn’t work with int, double and the like.

    It turns out that my confusion was caused by yet another nifty feature I had missed in the key-value coding documentation: the NSObject valueForKey: method automatically wraps its return value in an NSNumber object if the field it is querying is of a primitive type. Thus, in my code, NSString stringWithFormat: is never actually seeing primitive values, but rather NSNumber objects it can easily render.

  • As Jim Roepcke points out, I’m not the first person to have the idea of creating a templating mechanism for Cocoa. As it happens, the venerable MiscKit contains a framework called MiscMerge, which takes my idea and runs with it!

    In addition to the conditional branching I proposed in my previous post, MiscMerge implements loops, some convenient constants (such as date), a few commands, and the notion of a “global” dictionary of default values that can be set from the templates themselves.

    It’s a fairly impressive package, all in all, but after taking a look at it, I still think NSString+Templating has a reason to exist: namely, it’s simple! I had considered the idea of using an NSDictionary as a lookup table for tag replacement values, as MiscMerge does, but ultimately rejected it because I didn’t feel like writing the glue code to turn my model objects into into a hash.

    The thing I really like about my category is that it acts as a very thin bridge between the model and view (once again, thanks to the awe-inspiring power of the key-value coding pattern!). If you implement your model using proper accessor methods, you’re already most of the way there!

    That said, there is one problem with NSString+Templating that MiscMerge handles readily: what I like to call “out-of-band data.” The problem with my approach is that it’s possible that not all of the data needed to fill in the template is contained in every model object. There may be data that is common to every model “item,” and is therefore stored at a higher level in the application. With my approach, there’s no way to get that sort of data included in the merge (short of storing a copy in every model object, which would be dumb).

    Definitely something I will have to ponder…

  • I know only mad dogs and Englishmen are still reading this post at this point, but for the benefit of my own memory, I’d like to mention another thing this templating mechanism needs to handle: formatting of data for presentation. It’s entirely possible that users will not want data to go directly into the template, but rather would prefer it to be “cleaned” or otherwise formatted first.

    An example would be in code generation, where quotes in string literals need to be escaped. Or in markup languages, where certain characters need to be converted to entities.

Darth Vader’s iPod

Wednesday, October 22nd, 2003

From 0xDECAFBAD and (originally) Gizmodo comes news of the latest in a long line of “iPod killers”: the new iRiver iHP-120, which is, according to CNet, only a “hair” larger than the iPod and boasts Ogg Vorbis support (big with the Slashdot set).

My analysis: Apple security advisory should remain blue. I mean, how can this possibly be “the iPod killer” when the thing looks like part of Darth Vader’s outfit? I suppose I’m just a superficial Mac user, but I find it hard to imagine people choosing that monstrosity over the iPod!

Oh well—if you’ll excuse me, I’ve got equipment to lick!

NSString+Templating

Wednesday, October 22nd, 2003

I haven’t posted any code to this site for awhile, and I think that’s a shame. So I’m going to remedy that tonight by publishing a handy little NSString category I wrote for use in my personal projects. This category, which I have christened “NSString+Templating,” arose out of two things: first, my frequent observation that a quick and dirty text templating mechanism is a very useful thing to have around; and, second, the huge appreciation I’ve recently gained for the “Key-Value Coding” design pattern.

So, where to start…

For those who aren’t familiar with Objective-C, the language has a rather unique feature in the notion of categories. Essentially, categories allow programmers to add functionality to existing classes—not by subclassing them, as is common in OO languages, but rather by grafting new methods onto existing classes. Thus, anyone can teach Cocoa’s standard string class (NSString) new tricks rather than creating a subclass called “MyFancyString” or something (this approach has its pros and cons, natch).

As it happens, my category adds one method to NSString (yes, I realize the selector is rather long, but I couldn’t think of a more succinct way of expressing what the thing does!):


- (NSString *) stringByParsingTagsWithStartDelimeter: (NSString *) startDelim endDelimeter: (NSString *) endDelim usingObject: (id) object;

The first two parameters (startDelim and endDelim) specify what will be recognized as a tag (I’ve been using “< $" and "/>”), and the last specifies an object that will provide the values to replace the tags.

This last bit is where the key-value coding comes into play. To determine the replacement value for a given tag, this code will use the tag’s “name” as a key to query the object. Thus, if the text contains a tag called “< $firstName/>,” the code will query the object using the “firstName” key. If the object responds to that method, the tag will be replaced with its return value (if not, the tag will be replaced with nothing).

The value returned from the key method must be coercible by NSString stringWithFormat: (using the ”%@” format string) into text. Fortunately (and surprisingly), this seems to include all of the “primitive types” (int, double, etc.) and any object that implements a “description:” method. In most cases, it “just works!”

(Update: It seems I was correct about the primitive types “just working,” but I was wrong about the reason why. See my addendum for more information.)

The source and header files (I didn’t put them into a project, since I’m using Xcode exclusively now) can be downloaded here:

- NSString+Templating.dmg (9k)

If anyone has any improvements or suggestions, I’d be interested in hearing them. I can think of a lot of interesting places this could be taken in the future (adding conditional branching, à la Rael Dornfest’s “Interpolate Fancy” Blosxom plugin, would be one example).

Endurance

Saturday, October 18th, 2003

I’ve been busy lately. Really busy. As in, 4.5 hours of sleep a night, scruffy beard (I’m incapable of growing a good one, unfortunately), edge of collapse, “didn’t I once have a weblog?” busy. You’ve seen Al Pacino in Insomnia or Homer Simpson at the Kwik-E-Mart in “Lisa’s Pony?” That’s literally how I’ve felt the past few days. I’ve been in a training course at work, and Friday morning my head came this close to hitting the desk in front of me—thank God I caught myself nodding off, or it would have been both embarassing and painful!

All of this has taught me an important lesson: human beings (at least this one) can not work 12-14 hours a day without eventually experiencing adverse effects. I need some downtime! I need to simply sit down and watch my Futurama DVDs or read Wired or go up to Amoeba Music or something! Is that so wrong?!?

No sir, I don’t think it is! And that’s why I’m beginning to make plans toward transitioning out of the PodWorks business. It’s been an amazing run, and I couldn’t be more thrilled with the way version 2.5 (with its lovely new features, iPod 2.1 and Panther fixes, and completely rewritten, high-performance database parser) turned out, but software, like a shark, needs to move forward or die, and keeping up the momentum is going to be the death of me!

PodWorks users and (dare I say it!) fans needn’t worry, though. I’m not done quite yet, and if all goes according to plan, my baby will be very well taken care of in the future! More later…

The Best Windows Poster Ever Printed

Saturday, October 18th, 2003

The poster says it all, baby :-)!

Hell froze over: Introducing iTunes for Windows.  The best Windows app ever written.

Mobile Envy

Sunday, October 12th, 2003

Alright—I’ve had it! Between Rael Dornfest’s incessant Nokia 3650 talk, posts from both MobileTracker and The Tao of Mac on Nokia’s announcement of the new 3660, the added 3650 compatibility in iSync 1.2.1, and moblogs by Tim Shey and Alexander Payne, I’ve been rather disenchanted with the meager capabilities of my stodgy Motorola/Nextel phone for quite awhile now.

It wasn’t until I saw this month’s outrageous $290 phone bill, however, that I actually got angry about it—not only am I using outdated technology, it would also appear I’m paying top dollar to do it! Add to all this a free 3650 offer from Amazon.com and T-Mobile, and I’m beginning to feel like I’d be an idiot not to switch.

On the other hand, there is that unfortunate exploding battery thing

Storm Island & Other Adventures

Sunday, October 5th, 2003

The October National Geographic Traveler has a feature called “Experiences of a Lifetime,” which purports to explore “120 of the greatest cultural, spiritual and physical pursuits in the world.” Being a person who has always made an effort to do unusual, off-the-beaten-path things in my travels, I kind of enjoyed the article—even if a number of its picks (temple pilgrimages in India, Nepalese treks, etc.) fairly scream “retired bourgeois bohemian.”

Inevitably, though, reading the article reminded me that it’s been about six months since my last major trip (the point at which I usually get a serious hankering for some international travel), and that got me thinking about some of the more interesting, unfulfilled travel dreams I’ve had over the years. Since I’ve become cynical to the point where I consider nearly every thought that crosses my mind weblog fodder, I thought I’d share a few of them with the world.

(more…)