Vincent Gable’s Blog

August 3, 2008

How to Implement Automatic Updating

Filed under: Cocoa,Design,MacOSX,Objective-C,Programming,Sample Code,Usability
― Vincent Gable on August 3, 2008

If you are about to add automatic updating to your application (and you should), then check out the Sparkle Framework before you start. I wish I had done this before I spent a lot of time writing my own automatic updating code.

A quick-and-dirty hack.

Get your application’s version number by:
[[[NSBundle mainBundle] infoDictionary] valueForKey:@"CFBundleVersion"];
(This articles explains setting up Xcode to bake the current subversion-number into every build.)

Get the the latest version number out of a text-file on a website:
[NSString stringWithContentsOfURL:[NSURL URLWithString:@"www.your-url-here.com/whaterver/version.txt" encoding:NSASCIIStringEncoding error:nil]];
If there is any trouble, it will return nil. CAUTION: This will block the main thread for up to 30 seconds, while -stringWithContentsOfURL: tries to access the URL.

Making it Usable

If you don’t want your program to be unresponsive while it tries to get something off the internet, try this:

- (void) updatesReady
{
   //do something....
}

- (void) synchronousCheck
{
   NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];

   NSURL* latestURL = [NSURL URLWithString:@"http://www.your-url-here.com/currentversion.txt"];
   NSString* latestVersion = [NSString stringWithContentsOfURL:latestURL encoding:NSASCIIStringEncoding error:nil];
   //latestVersion will be nil if there trouble was accessing latestURL.

   NSString* ourVersion = [[[NSBundle mainBundle] infoDictionary] valueForKey:@"CFBundleVersion"];
   if([ourVersion isLessThan: latestVersion])
      [self performSelectorOnMainThread:@selector(updatesReady) withObject:nil waitUntilDone:YES];

   [pool drain];
}

//will call updatesReady iff a new version is ready, otherwise does nothing.
- (void) checkForUpdates
{
   [NSThread detachNewThreadSelector:@selector(synchronousCheck) toTarget:self withObject:nil];
}

A few thoughts on automatic updating:

When the user explicitly runs an update-check, they should get immediate feedback that something happened. You should put up a window with a spinner. Even though checking for updates may only take 100msec in your lab, if the user is on a flakey wireless connection while traveling, it could take several seconds for them.

It feels like it takes several years for an HTTP fetch to time out, if you can’t do anything while you wait.

Anything having to do with threads is harder then it looks.

“Check for updates {daily, weekly, monthly}” is a useless preference. Just because Apple’s Software Update has it does not mean you should offer those choices! They do not give the user any real control over when and how they are annoyed by requests to update. Users don’t care when the update checks are performed — they only care when new software is announced to them. Ether go with the a simple check-box that toggles automatic updating, or go with something like:
“Let me know about new software: at 12 PM”.

Display the date of the last successful update check, never display “Last Update Monday 9AM — update failed”. (This should be obvious, but I see it all the time). Version checking should be silent and unobtrusive. Don’t tell the user about it — only tell them about results.

Automatically downloading updates in the background is a great idea if they are small, and the computer has a reasonably fast internet connection.

You might also want to check out: NiftyFeatures 0.4 By Uli Kusterer .

An example project containing two classes, UKUpdateChecker and UKFeedbackProvider that can be plugged into your applications to add “Check for Update…” and “Send Feedback…” menu items to your applications.

July 23, 2008

Wow, Macs Really Are Easier

Filed under: Accessibility,Design,MacOSX,Usability | ,
― Vincent Gable on July 23, 2008

Atul Varma learns to love his Mac

…In a nutshell, though, I had always assumed that Macs were only marginally easier to use than PCs. I guess I’ve found over the past two months that in some ways, this holds true—the Mac is essentially an incredibly sexy-looking PC, with the same annoyances and a few polishes that make it a bit more humane to use. In other ways, however, the difference is truly like night and day.

This is a story about such a situation.

… I had to go through 8 wizards in all, so that’s a grand total of twenty-four clicks required to unplug my keyboard and mouse from one side of my computer and plug them into the other side. I’m not actually installing brand-new hardware here.

The first time I had to plug this keyboard and mouse into my Mac, I was floored. In the best-case scenario, I expected it to think for a second or two and then give me a reasonably unintrusive message informing me that I could use my USB mouse and keyboard. That would have been pretty humane.

But it did one better.

The Mac didn’t tell me anything, because my mouse and keyboard just worked the moment I plugged them in. When you plug in a power cable or a pair of headphones into a computer, you don’t get some kind of confirmation message from your operating system, because it’s obviously supposed to just work—why should plugging in a USB keyboard and mouse be any different?

… I have to admit that when it all adds up, I find my Mac to be significantly easier to use than my PC.

July 17, 2008

Null-Terminated Argument Lists

Filed under: Bug Bite,C++,Cocoa,Design,Objective-C,Programming,Usability | , , , , ,
― Vincent Gable on July 17, 2008

I was using +[NSDictionary dictionaryWithObjectsAndKeys:] to make a new dictionary, but one of the objects in the dictionary was the result of a call to a method that was returning nil, so the dictionary was incomplete.

This got me thinking about NULL/nil terminated argument lists. I don’t think they are a great idea (the compiler should be able to handle the list-termination for you!), but I think they are an especially bad idea in Objective-C.

The problem that it’s very common to have a nil object in Objective-C, relative to, say C++. Many Cocoa methods return nil on error. Since doing stuff with nil (generally) won’t cause an exception, these nils stick around much longer then in other languages. As you can see, nil is a pretty poor choice of a sentinel value.

It’s the 21st century! The compiler could tell an Obj-C method using a variable-argument-list how many arguments are in the list. This is trivial when all arguments are of type id. Since Obj-C methods use a radically different syntax from C functions, it shouldn’t effect existing C-code. Unfortunately, I don’t see this being added, because Objective-C is already so mature.

In the meantime. Be a little more suspicious of any objective-C methods taking a NULL-terminated list. I wish I had a perfect solution to avoid them, but I don’t! Sometimes they are the best way to do something. If you have a great work-around for constructing, say an NSDictionary with a variable number of key/values please let me know!

July 10, 2008

Money and Sales are Not a Metric for Good

Filed under: Programming,Usability | , , , , ,
― Vincent Gable on July 10, 2008

Sergey Solyanik recently explained why he left Google for Microsoft.

The second reason I left Google was because I realized that I am not excited by the individual contributor role any more, and I don’t want to become a manager at Google.

And I don’t know enough about Google or Microsoft’s management culture to offer any insight on this point.

I can’t write code for the sake of the technology alone – I need to know that the code is useful for others, and the only way to measure the usefulness is by the amount of money that the people are willing to part with to have access to my work.

He goes on to say that Microsoft measures everything in money, but at Google there are “eye candy” projects that are free, so he does not feel successful making them.

Now I feel the same way about writing code for the sake of technology alone. It is ultimately unfulfilling. And I have great respect someone who knows what they want to do, and does it. But I strongly feel that sales and profit are not the right metrics to measure how useful something is. There are several reasons for this

Customers and users are not the same thing.

Maximizing profits is distinct from, and often antagonistic to, maximizing quality.

The marketplace is too chaotic and relative to measure quality.

Ironically Microsoft Office 2008 For Mac is the perfect example. It’s the best selling version of Office for the Mac ever. If sales are a metric, it should be the best version of office. But it’s not (v5.1 may have this honor, at least for Word). Why it sucks is it’s own series ; I won’t go there for now. There are two big reasons why Mac Office 2008 sold so well in spite of it’s poor quality.

Firstly, there are more Mac users now then at any point in history. And Mac market-share is still rising. When 2.5x as many Macs are being sold today as 2 years ago it would be very difficult not to sell more copies of a popular Mac software package!

Secondly, 3 years ago, Apple switched from PowerPC to x86 microprocessors. Non-x86-native versions of office run excruciatingly slow on x86 computers. Microsoft made a “business decision” to not support Mac Office customers by denying them an x86-native update for versions of Office prior to 2008. There was a two-year period when the only Macs Apple would sell you had x86 processors, and the only version of office you could buy was not x86 native. This really sucked for users. But it paid off for Microsoft. They saved money by not supporting customers (which means higher profit, which is the only metric of good software, right?). But more importantly, it crippled older versions of office, which forced people to upgrade. People who would normally say “Well, I paid $500 for my copy of Office, and it may be old, but it does what I need, so I’ll skip the ‘upgrade’ and stick with ‘ol reliable, thankyouverymuch!” now had a horrible reason to upgrade. It isn’t that Office 2008 is so much better then other versions of Office, it’s that older versions of Office stopped working!

Customers != Users

I am a Mac Office 2008 user, but not a customer. Personally I think it’s is a shitty product, and I hate using it. But my employer’s IT department bought it for me, since it’s the only way to get Entourage, the lame Outlook clone for the Mac. And Entourage is the only way to get notifications from the company’s Exchange server whenever I get an email or calendar update, so I have to use it every work day.

You can’t look at the sale of Mac Office that I use and say “Vincent thought it was worth $500”, because that’s not what happened! What happened was that “Some company that Vincent works for thought it was worth $500…. because it played nice with their email server“. I hardly enter into the fucking equation at all! It’s more about the email servers then me, and I have absolutely no input on how the email servers were set up 10 years before I was hired.

Chaotic Market

And about that $500 figure ($499.95 is the estimated retail price of “Office 2008 for Mac
Special Media Edition”, and $500 is a nice round number so I’m sticking with it). Pricing is a black art. (That article is 5000 words, but I do think it’s worth reading). The only Office 2008 product I use every day is Entourage. But you can’t buy just Entourage, you have to buy it as part of an “Office 2008” bundle. And Microsoft loves to segment it’s pricing

So it’s unclear what you are buying, why, or how much of the money you give Microsoft is because of a clever pricing system, not clever software.

$1 does not mean the same thing to all customers. Obviously rich customers, say corporations, CEOs, etc. can pay more for something then the average Joe. Software that targets corporations or governments obviously will have a sticker price orders of magnitude higher then, say, a blog-authoring tool. But it is a mistake to conclude that just because a blogger can’t part with more money, that blogging software is less useful then “enterprise” email clients. Both fundamentally are communication tools, and both have changed the way that people interact.

Measuring “Good”

So how do you measure quality? There are several ways. User satisfaction, though hard to quantify, is probably the best. I recently attended a Red Cross training session on how to use AEDs. The teacher highly recommended the Zoll brand units we had purchased, and told us a few war-stories about how well Zoll-made equipment held up in the field, even after being dropped off the back of ambulances, and run over with a fire-engine. You only get high praise from your users by doing things right. (It’s possible to get praise from your customers by being cheap)

Another measure is productivity — how much more have people been able to do by using new software? This is quantifiable as time-to-complete-a-project or projects-completed-per-unit-time. However, it may be expensive to measure.

Unfortunately there is no silver bullet. Measurement is always difficult to do well — especially outside of a laboratory. Profit and sales are a data point. And they can tell you something — but they are not a good proxy for utility, satisfaction, or quality.

July 7, 2008

Getting OS X Icons

Filed under: Design,MacOSX,Programming,Reverse Engineering,Usability | ,
― Vincent Gable on July 7, 2008

This is what the Apple HIG has to say about icons. You should read it if you ever use icons. Even if you are not drawing your own icons, you need to understand how they should be used. (eg: icons in a toolbar should have a flat “head on” perspective, not the three-demensional look they have in the Dock.) You’ll find the icons you need faster if you know what they should look like.

Websites with icons you can use freely: IconDrawer, Iconfactory, Kombine.net.

SystemIconViewer (source included) by Noodlesoft is a useful tool. It lets you browse over 100 standard OS X icons that are available programatically.

For getting paths to private OS X icons, try poking around inside CandyBar.app — A commercial program that lets you customize just about any icon on your system. As of v2.6.1 /CandyBar.app/Contents/Resources/English.lproj/IconData.plist contains information on where icons are located. Icon locations do change completely between releases of OS X, even if the icon itself does not! I found CandyBar to be a better source of up-to-date icon locations then google. IconData.plist is pretty big and dense, but you can search it for keywords if you open it in Xcode, which helped me a lot.

(Although I haven’t used any of them personally, these are some design firms Apple recommends, if you have the cash.)

Rands First Law of Information Management

Filed under: Quotes,Tips,Usability | , , , ,
― Vincent Gable on July 7, 2008

Rands’ First Law of Information Management: “For each new piece of information you track, there is an equally old and useless piece of information you must throw away.”

Rands in repose

So true.

July 5, 2008

FourCharCode2NSString

Filed under: MacOSX,Objective-C,Programming,Sample Code,Usability | , , ,
― Vincent Gable on July 5, 2008

As I have written before, the best way to convert a FourCharCode to an NSString* for NSLog()ing is to use the NSFileTypeForHFSTypeCode() function. But for the life of me I can’t remember that name, even though I use it about once a month. It’s too long, and it has too little to do with what I’m using it for.

So I have added the line:
#define FourCharCode2NSString(err) NSFileTypeForHFSTypeCode(err)
To my prefix-files, because I can remember FourCharCode2NSString().

UPDATE: (2008-08-06) There is an even easier way.

July 3, 2008

Learning From Other People’s Failures: Acrobat Reader 9

Filed under: MacOSX,Usability | , ,
― Vincent Gable on July 3, 2008

Epic Fail.

The PC version is awful too.

June 28, 2008

Auto Dial

Filed under: Research,Usability | ,
― Vincent Gable on June 28, 2008

Today, most people I see making phone calls use cellphones. As near as I can tell, every time they call someone they know, they do it using their phone’s address book, instead of keying in their a ten-digit “telephone number”. It’s pretty obvious why. Nobody wants to have to memorize ten-digit numbers. And we think of people by their name, not some number.

This was not something that was hard to predict. Rolodexes have been in every office for decades, because people want to look up people by name, not number. Only recently has software supplanted them.

I was very surprised when I found this unknown invention from the late 1930’s

autodial.png
A NEW desk telephone directory not only finds the number you want but actually dials it for you. All you have to do is slide the knob on the face of the device, called an Auto Dial, to the name you want, then press the small lever at the foot of the machine. When the lever returns to its normal position, in five or six seconds, your call is made and you pick up the phone.

The Auto Dial was invented by a German before (World War II). The only sample in (America) is owned by Alfred Altman, President of the National Dairymen Association. The machine can handle any 50 telephone numbers desired by the user, and changes can be made at will.

The signals can be made up of any number of letters and digits, according to the system used in the local exchange. The regular hand dial on the telephone can be used in the ordinary way when the automatic device has been attached.

What an improvement over memorizing and/or dialing a number! We all have these devices built into our cellphones today. Frighteningly, the original appears easier to use then my cellphone’s “Address Book”.

So why didn’t this invention catch on half a century ago, not just a decade ago? I don’t know. I can only speculate, and I don’t think there is value in writing uninformed guesses down. But understanding why the Auto Dial was never popular is probably very instructive.

June 17, 2008

Every OS Sucks

Filed under: MacOSX,Programming,Usability |
― Vincent Gable on June 17, 2008

Funny, and true, video.

« Newer PostsOlder Posts »

Powered by WordPress