
The Myth About Reliability
Monday, 2009-04-27; 02:48:55
Kohl Vinh, over at Subtraction, wrote an article two years ago entitled “Designed Deterioration”, in which he writes about his cast iron skillet:
[I]t’s also a beautiful piece of design. After cooking in it and cleaning it up, I’ve spent a lot of time just looking it over, marveling at how its very deterioration has been incorporated into the design of the object, at how it’s gotten more attractive — less ignorant — the more I use it. I’m not particularly sentimental about much in my kitchen, but I would be heartbroken if you took away this iron skillet
He contrasts this with the wear and tear that his PowerBook had received:
Looking at the digital technology I own, what moderate deterioration to be found — dents in my laptop, a gash in the side of a laser printer I own, the accumulated grime on my computer keyboard — doesn’t make these items more desirable at all. In fact, when I see the way the corner on my aluminum PowerBook has been warped due to a nasty fall from a chair, I cringe. Through this obvious, glaring example of use, of accumulated knowledge, the object itself hasn’t attained an additional whit of beauty.
I first read this article over a year ago, and it’s always been in the back of my mind. Every few months a new editorial or a new video rant about how digital technology (especially products from Apple) is too much about form over function, about how it deteriorates way too quickly, and how computer manufacturers should concentrate more on making their products last longer. (Remember that whole hooplah about the iPod’s battery lasting only 18 months?) I also frequently see complaints from people when they have to bring their computer in for repair, and then have to wade through the inevitable complaints about how digital technology is trash.
My gut instinct is always to roll my eyes at these kinds of articles. And while Vinh’s article is probably one of the more eloquent ones to make this point, his article still elicits the same reaction from me.
Flawed Comparisons
My first thought about Vinh’s article is this: is he seriously comparing a suitcase or a skillet to a computer? Did he really just do that and expect us to take his article seriously?
For the most part, Vinh is comparing the outsides of computers, suitcases, and skillets. But consider the contents of each: a suitcase is designed to keep one’s belongings protected and all in one place. The typical contents of a suitcase are clothes. Clothes can be bumped and tossed around and won’t be the worse for wear. Clothes don’t have electrical components. Clothes don’t have connections. Occasionally you may be transporting fragile objects (like glass or maybe ceramics), but aside from their fragility (which can be mitigated with your clothes), they don’t have nearly as many potential problems with their innards as do computers.
In contrast, a computer’s contents are highly sensitive. If you get a single scratch or a single speck of dust on the platters of a hard drive, you lose data. If you spill liquid on the electronic components of a laptop, they typically short out and require replacement. If a connection inside your computer comes loose — one that isn’t user-serviceable like RAM or your hard drive — it’ll require opening up and removing so many parts inside the laptop which requires skill that most users don’t have.
And therein lies the answer to Vinh’s question about why we take pride in pristine looks of our computers but not in the pristine looks of our suitcases. It’s because of the contents of each. A computer’s contents are fragile, so we try to minimize nicks and cracks on the outside, the result of which could have caused problems on the inside. The higher the sustained damage of a computer on the outside, the more likely it is that damage has occurred on the inside. A suitcase doesn’t inherently have any fragile contents, so we’re not as concerned about the outside sustaining damage.
The suggestion that computer manufacturers have not designed for deterioration is actually pretty ludicrous, especially because beauty is in the eye of the beholder. Some people like the looks of scratched iPods.
Putting psychology aside, though, I question even the premise that suitcase or skillet manufacturers have designed for deterioration. My dad is one of the best cooks that I know, and he prides himself on having absolutely pristine pots and pans. Metal utensils are strictly forbidden when using his skillets; only wooden spoons and spatulas are allowed. (He breaks this rule occasionally, but he’s still very careful when using metal utensils.) It’s practically a sin to burn something on his pans, because it takes painstaking work (and is sometimes impossible) to get the burned material off.
It’s funny, because even Vinh himself cringes at the thought of having “seasoning” in his pan, the result of hundreds if not thousands of uses of the skillet. But then he goes back to thinking that his skillet is indispensable.
The reason Vinh actually doesn’t want his skillet taken away is because he’s found a skillet that works well for him. There are numerous little aspects of a skillet that make it enjoyable to use: the shape of the handle, whether the handle gets hot when you cook with it, whether the skillet is light enough to easily flip things with, the weight balance, the material used to create the skillet, etc. If I brought him a skillet that worked better in every way to his old skillet, I bet he wouldn’t hesitate to start using the new one.
A Better Analogy
I can also think of a number of other products that are decidedly non-electronic that don’t get better with increasing wear and tear. Bikes, for example, look worse when they’re dirty and dinged. Many buildings look like eyesores when they get dirt and smog and cracks on them. Even suitcases and skillets, to a degree, look pretty bad when they’re banged up.
Overall, I think that suitcases and skillets are pretty poor objects to which to compare computers.
Here’s a better analogy: cars.
Cars are designed to look pristine on the outside. When people get new cars, they try to delay that moment when they get their first ding. (My dad, for example, recently got a new car. Now he insists on parking in far-away spots that are at the end of a row, which only have one adjacent spot instead of two. If that requires parking in the next lot over, he’ll do it.) When people see an old classic car, they fantasize about buying it and fixing it up, and that includes getting a new paint job and banging out the dents and dings.
Not only that, but automobiles have reasonably complicated innards. They contain engines and moving parts and potentially flammable liquids, in addition to some electronics similar to what computers contain. More importantly, they always contain humans.
Is it any surprise that people are afraid to ding and bang up the outsides of their cars, when they contain ourselves?
Planned Obsolesence
Vinh’s ulterior motive for penning this article, I suspect, is motivated by a more pernicious myth:
Of course, the blame for the absence of designed deterioration from these products can be laid squarely at the feet of a more widely accepted design concept: planned obsolescence. I will probably never buy another skillet to replace the one I own for as long as I live, even though a new one is extremely affordable.
Bullshit.
Planned obsolescence is a myth, pure and simple.
The analogy of a skillet, here, is even more preposterous than the skillet’s use when talking about “designed deterioration”. A skillet doesn’t contain millions of electronic components, which, if broken, can cause issues when using the skillet. No, a skillet is composed of two things: the skillet and the handle. That a skillet is more durable and has a longer lifetime than a computer is, seriously, no fucking surprise at all.
Let’s go back to a more reasonable analogy: automobiles. Automobiles require constant maintenance and repairs, especially when they near the end of their life. Not only do you have to fill your car with gas, but you have to continually add oil. You have to add air to your tires. It’s recommended to have your engine serviced every 50,000 miles or so. Sometimes your transmission or radiator or carburetor breaks, and you have to spend hundreds or thousands of dollars to fix it.
Most people who use cars don’t have the expertise to repair their own cars, and when they take it to a mechanic, it often costs at least several percent of the original cost of the car.
Same for a computer. Usually, your computer works pretty well and without problems for the first year or two of its life. Then you start getting problems with the trackpad button not clicking correctly, or your optical drive failing to correctly burn DVDs, or your battery life starts deteriorating. Without constant maintenance or repairs to your computer, it can fall into disrepair and stop working.
Not only that, but computers can and do last a long time. The whole notion that a computer lasts a maximum of a few years is bullshit. Our family’s original Mac Plus, bought around 1986, still works. My original iMac, bought in 1998, still works to this day, without (if I remember correctly) a single repair. My G4 iMac, bought in 2002, still works. My dad’s aluminum PowerBook, originally purchased in 2005 or so, also still works. And it’s not really limited to Apple computers either. There are several computers still running Windows 95 at Stanford which operate expensive lab equipment.
More to the point, though, your bad experience with your computer does not indicate anything about computers as a whole. People make this mistake all the time. Repeat after me: the plural of ‘anecdote’ is not ‘data’.
I’m not suggesting that computers typically last decades like automobiles do. But they can. And with continual maintenance, you can extend the life of any computer for at least half a decade, if not more.
Do people really think that computer manufacturers sit in a room and decide the average lifetime of their products? Do executives really sit down and think up new features that use excess processing power simply to prevent older computers from running newer operating systems at acceptable speeds? Do people really think that computer manufacturers would not jump at the chance to improve the reliability of their products without significantly increasing the cost? Of course they fucking would. They’d trumpet and parade their newfound reliability in front of all consumers and other manufacturers (cf. Apple).
There’s no real reason to believe that intentionally shortening the lifetime of a computer would work to a manufacturer’s advantage, anyway! Moore’s Law takes care of obsolescence. Processor, memory, and graphics card technology are increasing so quickly, with programmers taking advantage of that increase in power so immediately, that even a perfectly functioning computer in pristine condition that lasts ten years would be hard-pressed to run cutting edge applications and operating systems. Sure, you can do it. But it’s ridiculous to expect that it will be able to run cutting-edge software at an acceptable speed. The pace of the computer industry is just too fast.
There are always new scientific applications and games that require more processing power, there is always new hardware and software innovations that take the place of older ones, and even if programmers optimized the crap out of operating systems and software, it wouldn’t take the place of the sheer processing power that newer computers provide. Time is simply better spent obsoleting older computers through faster hardware and newer software than trying to maximize the lifetime of an individual computer model.
The Human Computer
Reliability of hardware and even software is always a problem in the computer industry. Physical components break down, and software inevitably has bugs created by imperfect code that cause it to function incorrectly. It’s always worth it to try and find and fix bugs in software and to find ways to cost-effectively improve the reliability of hardware. But it’s also worth it to realize that the current situation is to be expected.
Think about the human body. It’s the result of billions of years of evolution of life on our planet. Modern humans have only been around for hundreds of thousands of years — a very brief period of time compared to the age of the earth — but humans have still benefitted from all the previous evolution of life.
And despite all that time, humans still have problems. Our organs still sometimes fail, requiring replacement. Bones still get broken in accidents. Humans still get sick from viruses as common as influenza.
And people expect computers — complicated tools created by humans — to not be subject to the same pitfalls that humans are?
Please.
Rants Permalink

On the Continuing MacHeist Controversy
Wednesday, 2009-03-25; 12:58:45
[UPDATE 2009-03-26: For everyone who doesn’t seem to get this: I know that the developers were not forced to participate in this bundle. That is irrelevant. And yes, developers will get a huge sum of cash up front. That is also irrelevant. I think in the long run it’s a bad deal for developers, and consumers should think about where their money goes. Why pay $39, a portion of which goes to MacHeist — middlemen who add no value to the actual apps themselves — when you can pay a little bit more and have all of your money go to the actual developers?
Put it this way: would you rather pay $10 to Universal Music Group for a music album, or $15 directly to the band in question?
Also, please see my three previous posts on MacHeist before commenting. Thanks.]
Gruber over at Daring Fireball writes:
I’m unsure why there seems to be lingering controversy regarding the new MacHeist bundle. My issue with the first MacHeist bundle two years ago was that developers were offered flat fees, rather than percentage cuts. Clearly this is no longer the case. Gus Mueller, critic of the terms of the original bundle, is participating in this year’s, and he puts it plainly:
So why is Flying Meat participating in MacHeist time around, when I blasted it a couple of years ago? Well, it’s pretty simple. The folks at MacHeist fixed the payment terms after MacHeist 1, and developers are getting a much better deal now. Tada.
Gruber is a smart guy. Sure, developers are getting percentage cuts now, but it’s hard to not come to the conclusion that developers are still getting screwed over, despite Mueller’s protestations to the contrary. I’m surprised that Gruber doesn’t see this.
Really, I don’t care about what Phill Ryu or John Casasanta said or didn’t say. Let’s do the math.
First off, let’s assume that the three “unlockable” apps will be unlocked this time around. (I mean, really, do they ever not get unlocked? It’s a stupid gimmick.) That means that the value of the bundle is $950.75, and $975.70 for the first 25,000 buyers. The bundle itself is selling for the “insanely low price” of $39. Let’s put into perspective really how “insane” this actually is.
Assume the percentage cut for each developer depends upon the value that app adds to the bundle. So we’ll use price as a proxy for the percentage cut that each developer makes. iSale is worth $39.95, so the iSale developers might be getting 39.95/950.75 or 4.2% of the profits. Pictureseque is worth $34.95, so its developers might be getting 34.95/950.75 or a 3.7% cut of the final profits. And so on.
Now, remember, 25% of the profits go to charity. So for every purchase of the bundle, $9.75 gets lopped off the top. Of the leftover 75%, iSale gets 4.2% of the cut, or $1.23.
Let that sink in. The developer of iSale is getting $1.23 for a single license of iSale, rather than the full $39.95. The iSale developers are devaluing their own product, supposedly [EDIT: striking out the weasel word, thanks Flooey] of their own free will, by 97%. In fact, all developers are devaluing their product by 97%.
| App Name | Percentage Cut* | Profit per Bundle Sale |
| iSale | 4.2% | $1.23 |
| Picturesque | 3.7% | $1.08 |
| SousChef | 3.2% | $0.92 |
| World of Goo | 2.1% | $0.62 |
| PhoneView | 2.1% | $0.61 |
| LittleSnapper | 4.1% | $1.20 |
| Acorn | 5.3% | $1.54 |
| Kinemac | 31.4% | $9.20 |
| WireTap Studio | 7.3% | $2.12 |
| BoinxTV | 20.9% | $6.12 |
| The Hit List | 7.4% | $2.15 |
| Espresso | 8.4% | $2.46 |
Kinemac, which regularly retails for $300, is not even getting $10 for each sale of the bundle. Who in their right mind would do such a thing? I mean, really? Talk about insane.
This is all assuming that Phill Ryu and John Casasanta get no cut whatsoever. This also assumes that the developer of Big Bang Board Games also gets no cut. Who knows what percentage Ryu and Casasanta are taking this time around? The iSale developers are probably getting $1, not $1.23, for each bundle sold.
Fundamentally, what it comes down to is that those consumers who are participating in the MacHeist bundle are tightwads. Even if you’re only interested in one of the apps in the bundle, it’s likely that only a little more than one of your dollars is going to the actual developer of that app. And you’re doing it all because you can get that app for a really cheap price, especially if you’re looking to get BoinxTV or Kinemac, which normally cost $200 or $300, respectively.
And people are complaining at the bargain basement prices of iPhone apps.
Marco Arment is being nice when he says:
My point is whether it’s a good idea, as conscientious consumers, to accept such steep discounts on the products that we use and love.
My argument is that it’s not.
Let’s just say it like it is, Marco. If you’re buying MacHeist, you’re a cheap fucking bastard, and it makes me queasy that so many in the Mac community would buy into such a thing.
Rants Permalink

Checking for Weak Linked Frameworks
Saturday, 2009-03-07; 22:15:46
Let’s say you have an Xcode project, and you’d like to have support for a non-essential framework. Typically, when you add a framework to a project, you go to [Project —> Add to Project…] and select the framework you’d like to add. This is linking. However, this method causes your program to simply not launch if that framework isn’t present. This is bad.
So to let your program still run even when the framework in question isn’t present, you weakly link the framework instead. Apple has some good docs about weak linking that explain the details.
Suffice it to say, if you’re weak linking a framework, uncheck the target membership box in the project sidebar for the framework you want to weak link, then get info on your target and add “-weak_framework framework_name”, where “framework_name” would be “SDL_mixer” if you want to weak link SDL_mixer.framework.
Apple’s documentation also helpfully includes code that you can use to check whether or not the framework in question is installed or not. Instead of specifically checking for the framework, you simply check if the pointer to the function you’re about to call from that framework actually exists. Here’s the code from Apple’s docs:
int result = 0;
if (MyWeakLinkedFunction != NULL)
{
result = MyWeakLinkedFunction();
}
So you check if MyWeakLinkedFunction exists, and then execute it if it does. Now take a look at a QuickTime movie of me debugging an example of such code. No, I’m not debugging with optimization on, and ignore all the other weird stuff about this code like the duplicated lines. Just focus on which lines the debugger goes through.
Mix_OpenAudio is a function from SDL_mixer, correctly weakly linked in my project. Notice that the debugger simply skips over the first Mix_OpenAudio if statement, and skips the entire second #ifdef __macosx__ block, even though __macosx__ is clearly defined since the debugger went through a similar #ifdef __macosx__ block at the top.
What’s going on?
The short explanation is that Apple’s suggested code simply doesn’t work.
Here’s what’s happening. When you compile on Leopard, Mix_OpenAudio, or MyWeakLinkedFunction as in the case of Apple’s sample code, always evaluates to true regardless of whether the framework is present or not. So in the movie of me debugging, the line if (Mix_OpenAudio == NULL) always evaluates to false. The compiler simply doesn’t compile those lines of code because of this, which explains why it simply skips over that if statement. The compiler actually generates an “always evaluates to true” warning if you change the line to if (Mix_OpenAudio).
Similarly, the second identical if statement inside the #ifdef __macosx__ block also always evaluates to false, and so the compiler omits that entire block, since no lines of code will ever be executed regardless of the outcome of the if (gameOptions [0].sound.bUseSDLMixer) { line.
Apple’s docs spout BALD-FACED LIES.
A Google search for “compiler weak linking” actually produces the solution as the second search result. Instead of the Apple sample code in the docs (as reproduced above), use this code instead:
int result = 0;
uintptr_t address = (uintptr_t)(MyWeakLinkedFunction);
if (address != 0u)
{
result = MyWeakLinkedFunction();
}
You need to specifically get the address of the function as a uintptr_t, and then test its equivalence to the literal “0u”, not “0”.
Thanks Richard Wright, I’m glad you posted your solution to the internets.
UPDATE 2009-03-11: Actually, it looks like that (now striked-out) solution doesn’t work either. This was working fine in a debug build, but when I finally made a release build, the program crashed yet again when the weakly linked framework was not present.
After banging my head against the wall for a long time, I finally e-mailed the Cocoa-Dev mailing list, and Greg Parker from Apple helpfully suggested that the compiler was optimizing my code out. He also included some other code that isn’t optimized out, and I have confirmed that it works under both Debug and Release builds:
int result = 0;
void * volatile function_p = (void *)&(MyWeakLinkedFunction);
if (function_p != NULL)
{
result = MyWeakLinkedFunction();
}
Software Development Permalink

Report Finds Internets are not 1/3 Pedophiles
Thursday, 2009-01-15; 19:51:35
My dad used to have a saying about chatrooms on the internets: 1/3 of them are teenagers, 1/3 of them are “sexual predators” going after those teenagers, and 1/3 of them are undercover FBI agents trying to catch the predators.
Unsurprisingly, when studies are actually done, it turns out that there’s not really a problem with underage sexual solicitation on the internet. So concluded the Safety Technical Task Force, which was created by attorneys general of 49 states in the U.S.
According to the New York Times:
The task force, led by the Berkman Center for Internet and Society at Harvard University, looked at scientific data on online sexual predators and found that children and teenagers were unlikely to be propositioned by adults online. In the cases that do exist, the report said, teenagers are typically willing participants and are already at risk because of poor home environments, substance abuse or other problems.
Furthermore:
Among the systems the technology board looked at included age verification technologies that try to authenticate the identities and ages of children and prevent adults from contacting them. But the board concluded that such systems “do not appear to offer substantial help in protecting minors from sexual solicitation.”
Unsurprisingly, Richard Blumenthal, attorney general of Connecticut, “said he disagreed with the report”, says the New York Times.
When is it going to get through to people that this isn’t a problem? I don’t think it ever was a problem. Throughout my life, I’ve participated significantly in chatrooms on Hotline (remember that?), GameRanger (remember that?), various message boards, instant messenging, and website commenting all when I was under 18, and I never once got approached by anyone for sex.
In fact, the internets have significantly improved my ability to do things with random people that never would have happened otherwise. I helped people fix problems on their Macs. I wrote documentation for a programmer in Belgium who wrote a Hotline client. I’ve learned a whole lot about Mac and iPhone development via Twitter. All by communicating with people I hadn’t known before and whom I had never met in person.
Furthermore, I’ve met many, many people in person whom I first met online. I’ve never had a problem with any one of them. I’ve met some oddballs, and some people who I probably don’t want to meet again, but I’ve never been in any danger.
When are people going to realize that this is false outrage? When are we going to stop devoting so much money and effort and time to try to stop a problem which doesn’t exist? Meeting and conversing with people on the internet is pretty much the same as meeting and conversing with people in person. You just have to be a little more cautious.
Would you give your physical address to someone the first time you meet them in person? No. So then don’t do it with someone you just met on the internet.
How do you meet someone in person whom you first met on the internet? The same way you do when you first meet someone in person: you’re almost always in a public place, during the day, maybe with a friend or two, maybe over coffee or something.
When do you trust someone from the internets enough to give them your phone number? After you’ve talked with them a few times, you get to know a little bit about them, after you’ve met them in person, etc. This is probably less of a big deal now that cell phones have proliferated everywhere, and you already have a means of communicating with someone whom you met on the internet.
Seriously, it’s not that hard to exercise common sense.
Rants Permalink

Whither IM-to-SMS in Leopard
Sunday, 2009-01-04; 23:39:17
In iChat in Tiger, you could add a “buddy” to iChat in the form of “+1##########”, where the #s are digits from 0-9 representing an area code and a phone number in the US, and you could send an IM to that “buddy”, which AOL would deliver as an SMS to the phone at that number, for free.
When I upgraded to Leopard, this initially worked. However, now it doesn’t. Currently, when you add a buddy like that, it immediately goes offline. When you attempt to send an IM to that buddy while offline, iChat simply throws an error message saying that the buddy isn’t online, and doesn’t deliver the message.
However, I’ve tested this feature on Macs that still run Tiger, and the feature still works. So it seems that AOL hasn’t discontinued the free IM-to-SMS service.
Is this a case of Apple removing the feature from iChat in a Leopard update? (I can’t remember exactly when it stopped working, because I only rarely use it.) Or can other people still use this feature? If it still works in Leopard for others, what am I doing wrong?
[UPDATE 2009-03-11: It turns out that it was a user-specific problem. If I logged in under another account and used iChat with my normal AIM profile, this feature worked perfectly. It just wasn’t working under my existing user account.
I filed a bug with Apple on this problem and informally heard that the problem was being punted to the next major release of OS X, version 10.7. But two months later, I noticed that my wireless buddies were suddenly being shown as online again, and the SMS feature now works in my existing user account again. It didn’t seem to be connected to any specific update, either. Weird.]
Tips Permalink

The "Visible At Launch" Gotcha
Saturday, 2009-01-03; 04:43:03
When I use sheets in a Cocoa project, I often put the sheet in its own nib file. I create a subclass of NSWindowController that handles sheet dismissal, and includes the sheet callback method as well as methods that respond to button clicks on the sheet. Then when I need that sheet, I just allocate and initialize a new controller, which calls NSWindowController’s -initWithWindowNibName: method to load a copy of the sheet from the nib.
Typically a sheet is only associated with one kind of parent window (like a document editor window), meaning it usually makes sense to simply include the sheet inside that parent window’s nib. But putting the sheet in a nib by itself is useful if you have a lot of different kinds of windows, but you want to be able to attach an identical sheet to any one of them. This is what I do with kill sheets in Memory Usage Getter, since they can attach to both the Tab View and List View windows, as well as to individual process history windows.
I was using the same technique when adding some sheets for TidyWeblogger, except I was encountering a weird problem: the sheets weren’t attaching to windows like they were supposed to do. I was passing a valid reference to the sheet and to the parent window when using NSApp’s beginSheet:modalForWindow:… method, too.
Instead, the sheets just appeared in midair, attached to no window in particular, and as such, they couldn’t be moved around either. Furthermore, when I clicked a button to dismiss the sheet, they didn’t go away immediately. They only disappeared from the screen when I started interacting with a different window.
I posted about this problem on Twitter, and Fraser Speirs pointed out the problem:
In the nib I created for my sheet, the “Visible At Launch” box for the sheet window itself was checked in the Behavior section of the Attributes inspector tab. As soon as the nib was loaded, the window would appear, instead of waiting for me to tell the sheet to attach to a parent window.
The fix is simple. For any sheets, make sure the “Visible At Launch” box is not checked. After saving the nib and recompiling, everything worked perfectly.
Software Development Permalink

Sort Descriptors, NSTableView Bindings, and You
Tuesday, 2008-12-23; 03:13:45
So if you’re using an NSTableView, an NSArrayController or an NSDictionaryController, and bindings to link the two, here’s a problem you might run into.
In Interface Builder, you can set NSTableViews to have autosave names, which allow table views to automatically save and restore various “settings” about the table view, like the column positions, column widths, hidden columns, column sorting, etc. Just by virtue of giving the NSTableView an autosave name in Interface Builder, it should start saving and restoring all of these settings.
It was the column sorting that was giving me trouble. Column widths and column positions were being saved perfectly fine, but my column sorting was always being reset to a default value after each launch. This problem pissed me off for a day, and looking through various documentation didn’t help, because it suggested that sort descriptors should be autosaved and restored.
Other oddities with this problem is that it seemed that the NSTableView was saving the sort descriptors to my app’s plist preference file, but wasn’t restoring it. I tried binding the NSTableView’s sort descriptors to an NSUserDefaultsController, and even that didn’t work. I tried manually getting the preferences via an NSUserDefaults object, hoping to programatically set the NSTableView’s sort descriptors on launch. What was weird was that when I tried to retrieve the sort descriptor settings that were clearly saved to the preference file, the NSUserDefaults object was returning null values for that key.
I’ve seen a few posts about this, but no answers. Because the almighty Google indexes all, I thought I’d post my solution.
The issue is that your NSArrayController or NSDictionaryController also has sort descriptors, and these seem to take precedence over the NSTableView’s own sort descriptors. But these sort descriptors don’t get autosaved along with the NSTableView’s other settings. So while the NSTableView does seem to save the sort descriptors, it would seem that it attempts to restore them but then they get obliterated by your NS*Controller’s sort descriptors, which are reset to default values on every launch.
The solution here is to bind your NSArrayController’s (or NSDictionaryController’s) sort descriptors to an NSUserDefaultsController. Select your controller, switch to the bindings tab in the inspector, and then click the “Sort Descriptors” disclosure triangle under the “Controller Content Parameters” section.
Check the “Bind to:” box, and select “Shared User Defaults Controller”. (This will automatically create an NSUserDefaultsController instance in your nib.) Set the controller key to “values” and the model key path to the key you want to use in your prefs file (for example, “sortDescriptors” is fine). You’ll need an NSUnarchiveFromData value transformer, and you’ll also want to check the “Validates Immediately” box so that your sorting gets saved to prefs as soon as the user clicks a column heading to change the sort order.

You’ll also want to make sure that your NSTableColumns have sort keys and selectors. This is easily done in Interface Builder as well. Select each of your NSTableColumns in turn (the inspector should start with “Table Column” if your column is correctly selected), and switch to the Attributes tab. For “Sort Key”, you’ll want to enter the model key path to your column data (in my case, my bindings controller key for the column is “arrangedObjects” and the model key path is “value.entryTitle”, so I put “value.entryTitle” in for my sort key). For “Selector”, type in a method name that tells your program how to sort your NSTableView items (for example, “compare:” or “caseInsensitiveCompare:”). Do this for each table column.

You should probably unbind your NSTableView’s sort descriptors as well, if you’ve left them bound from pulling out your hair trying to figure out this problem.
I’m not sure if I would classify this as a bug or not. Is there any time when you would want sort descriptors for both the NSTableView and the NS*Controller that’s providing the NSTableView with data? Otherwise, NSTableView’s sort descriptors bindings should probably be grayed out when its corresponding controller is connected.
In any case, hopefully this helps anybody else who comes across this problem.
Software Development Permalink

More TidyWeblogger Stuff
Friday, 2008-12-19; 17:39:18
As TidyWeblogger has taken over the job of posting entries to my weblogs, I found that my motivation to continue to develop the app has rapidly increased. Here’s what’s changed in a little over a week.
TidyWeblogger is now generating every single page on my weblogs. Category pages, archive pages, entry pages, main page, RSS feed, dummy files, and a new addition, a JavaScript file that just contains an array of recent entries to use on other pages. I’ve republished all pages so that they conform to my new templates, and everything’s working just dandy!
Take a look at the new archive sidebar item, as well as the new archive page itself. The category stats are once again being updated, and the browse by date archive page is simply one long list of all entries on a single page. I realized there’s no need whatsoever to have separate month and year archive pages, since it’s just a bunch of unnecessary clicks when a single page can present all the necessary information all at once. It’s also convenient if you’re looking for an entry and not sure when it was posted.
JavaScript improvements have been made across the board. And by “improvements” I mean that a lot of JavaScript has been ripped out. iBlog created HTML files that constantly referred to the CommonLib.js file to create the sidebar items, the weblog and category titles, etc. My templates do all this generation beforehand and create mostly static files.
It takes more time on my end, but I prefer that to more JavaScript on my pages. For example, since the category stats are all static, all pages need to be regenerated when I publish a new entry in order for the stats on all pages to be accurate. This is another case where it makes sense to publish a separate JavaScript file with the category stats, and have all pages get the stats from that file so that every page doesn’t need to be regenerated.
In any case, the only things that JavaScript is handling now is the Linkable Supernova sidebar item creation, and comments. Category stats will probably be migrated back to JavaScript at some point.
I mentioned that TidyWeblogger creates dummy files. It’s been doing that for a while: dummy files are needed in order for the comments system to work. But I’ve added a new class of dummy files that TidyWeblogger creates now: for those entries that have the old crufty URLs from iBlog (the ones like “http://homepage.mac.com/simx/technonova/C486203617/E20071118034738/index.html”), TidyWeblogger creates a redirection page that points to the new URL. Old comments on the new page are preserved, too. In this way, both the old URLs are preserved, but everyone sees the new ones since the crufty ones redirect to pretty ones.
I also mentioned the new JavaScript file of recent entries. This allows me to retire that ridiculous hack that I was using to get a self-updating list of Linkable Supernova entries in the sidebar here. Technological Supernova is no longer loading 11 invisible iframes with pages from Linkable Supernova just to get the titles of the pages.
The result is that loading pages here should be much faster now, and this should be especially noticeable on the iPhone or iPod touch. It just now loads the RecentEntries.js file for Linkable Supernova, and then writes the list to HTML via JavaScript. It’s much more reliable, too — previously, it used to fail to write any links sometimes.
Also, eliminating this hack allows my pages to validate again, at least according to the W3C validator. Previously, it was throwing an error because I was using an “onLoad” attribute for the iframes. I know, I know, validation shouldn’t be an end goal in and of itself, but it’s still a good indication of using web standards.
Speaking of validation, TidyWeblogger is using NSXMLDocument’s NSXMLDocumentTidyHTML option so that any generated content is transformed into valid XHTML automatically, as much as possible. There are some validation errors it can’t correct, like adding a title attribute to all images, though.
Various other things have been fixed: I can force TidyWeblogger to republish all entry pages in one action, now. Entry published dates now automatically update in the main window after a publish, and comments now will get enabled on publish even if the initial publish fails.
I think another factor in my excitement to develop this app is that I’m learning a whole ton of new stuff in Cocoa programming, some of which stems from the Leopard improvements. Here’s what I’ve learned over the past few days:
Bindings! I’ve finally gotten around to seeing the benefits of these things. My initial attempt at bindings in TidyWeblogger was pretty unseemly because I was using a dictionary of entries with an NSArrayController, which controlled a proxy object that I would update programatically to synchronize with the dictionary of entries.
I later used bindings on a smaller problem, implementing an NSDictionaryController to control the values and titles of an NSPopUpButton. Then I back-tracked and re-factored my initial attempt at bindings, with great success.
Bindings are really useful to eliminate glue code when initializing interface objects in an entry editor window, for example. There’s absolutely no code whatsoever to make the popup buttons present the correct categories according to the relevant weblog, which is nice. It also eliminates the need for any manual sorting code that was necessary when I created Memory Usage Getter; my table view of entries is automatically sortable by title, category, and date simply because it’s using bindings.
I finally figured out how to use the replacement for NSCalendarDate. You need to use a combination of NSDate, NSCalendar, and NSDateComponents. This is a change that came with Tiger, and it seems to have been done to accomodate calendars other than the Gregorian calendar which is used in the United States.
Creating toolbars in Interface Builder. This is incredibly useful, because it eliminates the need to create any code for getting toolbars and their buttons to work. You just drag and drop them into your window, and then connect outlets and actions just like you would do for a standalone NSButton.
I’ve been using more Objective-C 2.0 paradigms, like fast enumeration, which is pretty useful. I haven’t started using @property and @synthesize declarations yet, but now that I’m using bindings, I can see exactly why and how they’re used.
Some of my coding conventions have slowly been changing as well. Instead of using the alloc-init dance for stuff like NSMutableArrays and NSMutableDictionaries, I’ve started just using the -array and -dictionary constructors so that I don’t have to worry about releasing the objects later. Similarly, my setters have gone from retain-then-release to equivalence-release-allocate to accomodate the setting of mutable objects from immutable counterparts.
One of the things I think I’m most proud of in my code is that the method that’s generating all the HTML files is highly extensible, and I’ve only had to make minor modifications to allow the creation of archive pages, entry pages, main pages, etc. It’s pretty sweet.
It’s especially great because when I want to add new template entities (things in the page templates like “{[ENTRYPAGEURL]}” which TidyWeblogger dynamically replaces according to which page is being created), I can do it once and not worry about it again.
My goals for future development, roughly in order:
- Publish category stats to a separate JavaScript file and have entries point to that instead.
- Investigate why stylesheet cookies seem to not be consistently working. Also, I’ll see if I can eliminate the flash of the sidebar in the wrong position.
- Figure out why my table view isn’t auto-saving sorting. Column positions and sizes are being auto-saved, though, so I’m not sure why sorting isn’t. Can anybody help out with this?
- Figure out how to get the table view to re-sort when information is updated, like the publish date.
- Figure out why my NSTextView is loading with small fonts for Markdown entries.
- Thread my interface. Currently, publishing freezes the interface for minutes at a time if there are a lot of entries, because it’s all running in the main thread.
- Figure out why undo isn’t supported in my entry NSTextViews.
- Implement the dirty dot for entries, and update the entry composition windows with entry titles.
- Test a few things that I haven’t been doing often, like reverting an entry, changing an entry’s category, or changing it’s custom URL. Make sure these all work.
- Fix the last remaining feature that’s still disabled: the next and previous links on the entry pages. I might punt on this for a bit, because this may require some refactoring, again.
- Implement the .Mac SDK (has it been renamed the MobileMe SDK yet?), so that I don’t have to rely on my iDisk being mounted in the Finder when publishing.
- Implement local storage and composition of entries, and synchronization of local entries with the iDisk so that you don’t have to compose entries while online.
That’s a tall order, but since I’ve been making rapid progress anyway, a lot of this stuff might get done sooner rather than later.
Yay development!
Software Development Permalink

Smallish TidyWeblogger Update
Wednesday, 2008-12-10; 03:31:23
Just a quick little note to say that I’ve managed to refactor my TidyWeblogger code so that it now handles multiple weblogs. All Supernovas (well, except the Italian translation, which I think I am retiring) can now be published from my app, which is good news. I may even bring Linkable Supernova back from the dead. I’ve missed it.
Things that will happen in the near future:
- another refactoring because the way I’m using NSArrayController is wrong, and it’s kind of appalling that I managed to get it to work anyway
- control of the sidebar via templates
- republishing of all individual entry pages when doing a Publish All (currently, all that is recreated are the index.html, rss.xml, and category pages)
- fix a bug where comments don’t automatically get enabled if the first publish fails
- fix a bug where publishing an entry for the first time doesn’t update the publish date in the main list of entries
Yay? Here’s a screenshot:
Software Development Permalink

No, Microsoft's Ads Aren't Genius
Friday, 2008-09-12; 01:06:12
Microsoft’s new ad campaign with Jerry Seinfeld isn’t genius. It’s just stupid. What a shocking supposition, right? Well, to my surprise, apparently not all people think so. Daniel Jalkut posted an article today positing that the Jerry Seinfeld ads are “as close to genius as Microsoft could ever dream of coming”.
I think refuting this hypothesis is best done point-by-point.
Most critics of these ads point out, quite rightly, that the message doesn’t ask viewers to buy anything. If an ad doesn’t ask you to buy something, surely it’s a failure. […] If you want to criticize these ads, come up with something deeper than their failure to clearly condense into 30 seconds what purchasing action a consumer should take!
There are two types of ads, one which directly pitches a product to the viewer, and one which pitches a brand to the viewer. Microsoft’s ads are a form of the latter.
Brand ads, though, actually have two types as well; the competitor brand ad, and the monopoly brand ad. With a competitor brand ad, the company is positioning itself so that when consumers think of a specific type of product (e.g.: routers), the consumer will automatically associate that type of product with a specific brand (e.g.: Cisco). Cisco’s infuriating “Welcome to the Human Network” ads are a perfect example of this. Cisco’s products (chiefly routers, which basically pass packets back and forth) don’t really have anything to do with creating a “human network”; rather, they simply create a “network”. But the ads are effective because they’re touchy-feely, and make viewers feel good.
With a monopoly brand ad, however, the company is trying to enhance the company’s public image, with the goal of making consumers feel better about buying that monopoly’s inelastic product. The key word here is “inelastic”. We’re talking about products that consumers would buy anyway, even if they have a negative opinion about the company who makes that product. The consumers already understand the utility of the product, and they’re already going to buy it; they’re just not comfortable with the company from which they’re buying the product. A good example of these kinds of ads are the infuriating ExxonMobil ads, which insinuate that the company is doing a lot for the environment, when they’ve actually been fighting tooth-and-nail for decades to lower the payoff due to the catastrophic Exxon Valdez oil spill, and were sadly successful.
Microsoft’s ads fit into neither of these two categories. Microsoft isn’t really a competitor in the computer market; it’s effectively a monopoly. Sure, there’s Apple and Linux, but they hardly pose a threat to Microsoft in the consumer market. Pitching the brand to viewers doesn’t really help because people almost automatically buy Windows PCs when they buy a computer. (This is slowly changing what with Apple’s extremely excellent product lineup.)
But Microsoft’s products aren’t inelastic. So a monopoly brand ad isn’t going to work for them either. The problem that Microsoft has is that their products just don’t work. Their products don’t have value to the average consumer. Consumers aren’t automatically going to go out and buy Vista like they would gasoline from ExxonMobil. Consumers use Vista simply because it’s been preloaded on their new computer. They aren’t upgrading to Vista because Microsoft hasn’t convinced them of the benefits of Vista over XP. Microsoft’s Mojave Experiment ads are a testament to this.
Microsoft’s fundamental problem is not that they have a public image problem. They have a product problem. Consumers don’t value their products. Microsoft doesn’t make products that are head and shoulders above other products. They’re bland, they’re problematic, and Microsoft can’t even convince consumers that they’ve bested their old product!
It’s a product problem. The bad public image is fundamentally due to the product problem. Microsoft can’t fix this with brand ads. They can’t even fix this with product ads. They need to fix their product first.
If you’re Microsoft, and you’ve grown tired of these assessments, you wouldn’t have to be a rocket scientist to realize that owning 90% of the market and having a bajillion dollars … is a pretty good place to start from, in turning around your public image.
If you’re a Microsoft exec, and you’re smart, you’d be investing this money in improving your products, not investing millions in a misguided ad campaign that is not going to do anything to change the perception that your products are flawed.
Again, Microsoft needs to fix its products before it can fix its public image.
These people are expecting something cliche from Microsoft, and instead the company has handed them a revolution. While Seinfeld’s collaboration with Microsoft has been widely heralded as a long-overdue reaction to Apple’s Mac/PC ads, Microsoft has instead taken a completely different path. And people can’t stand it.
People expect something “cliché” from Microsoft, because Microsoft’s products are fundamentally flawed. Instead of addressing the core problem, Microsoft comes out with yet another set of ads. Consumers are tired of it! They want a better product, not more ads!
The only reason why it’s becoming a headache for Microsoft now is that Apple has finally gotten to the point where it’s convinced consumers that their products offer better value. This wasn’t the case for the first part of this decade.
I propose that Microsoft’s ads, with their mysterious yet evocative plot, are the most creative and purposeful ads ever to come out of the company. While devoted Apple fans might relish in declaring them an utter failure, I make the opposite assessment. These ads are the last best hope Microsoft has at erecting a dam in the face of a tidal shift towards Apple.
Seriously? You think the best thing that Microsoft can do to stop the “tidal shift” towards Apple is to come out with a weird ad campaign, rather then fix their products!? If that’s the case, then I’d question whether Jalkut is fit to run a large company.
We’ve seen this problem before with another company: Apple. In the late 1990s, Apple’s public image was in the crapper because of… you guessed it… crappy products. But Apple was in a different situation than Microsoft, because it wasn’t in a de facto monopoly position. And Apple came out with a competitor brand ad, the Think Different campaign. Apple wanted people to automatically associate computers with Apple.
But I’ve seen no evidence to support the claim that the Think Different campaign turned Apple’s fortunes around. In fact, it’s practically undisputed that it was an Apple product, the original iMac, which made consumers realize that maybe Apple’s products had value. The iMac was cheap, it had a fast modem (so that one could browse the internet at what was then a fast pace), and it allowed one to get on the internet in three easy steps (there’s no step 3).
It wasn’t the ad campaign that turned Apple around. It was the products. After the iMac, Apple kept on hitting the target with valuable products: colored iMacs, iBooks, upgraded iMacs, upgraded iBooks, PowerBook G4, etc. The only two products in the last decade that could possible be termed “failures” for Apple are the G4 cube and the iPod Hi-Fi. Every other product has pretty much been a hit with consumers.
With these first ads from the Seinfeld era of Microsoft marketing, we see a company that is no longer simply spittling up blood, but instead spraying it in the face of its opponent. If Apple has been wondering when the competition will strike back, the answer is now. With a vengeance, albeit a somewhat mysterious one.
Oh come on. “With a vengeance, albeit a somewhat mysterious one”? What the fuck does that even mean? This reminds me of the time I read an article in the San Francisco Chronicle that said, “[t]he brink of what remained unclear.”
You can’t strike back “with a vengeance” but be mysterious at the same time! This is just an attempt to justify the argument with phrases that sound good, but when you think about it, are really just plain stupid.
So if you think the ads suck, don’t worry, you’re not the target audience. Laugh away!
Oh, I get it. If we raise any objections to Jalkut’s argument, then we obviously aren’t the “target audience” and so our opinions don’t matter. That’s a brilliant way of arguing your point; anybody who disagrees with you is painted as insignificant!
This smacks of the same arguments that many used to defend MacHeist. “Of course your opinion doesn’t matter because you aren’t one of the developers participating in the promotion!” If you actually think about this argument, it’s basically saying the same thing that Jalkut is saying: anybody who disagrees with you shouldn’t be allowed into the argument.
Jalkut’s article sounds basically like someone who wants to take an opinion contrary to everybody else just for the fun of it. But when you analyze his argument, it doesn’t hold up to scrutiny. Usually, when an advertisement makes you scratch your head and go, “Huh?”, it’s not evidence of a brilliant ad campaign, it’s evidence of a stupid one.
Rants Permalink













