Carl Ellison (a cryptographer at Intel, a great guy) formulated what I call Ellison’s Law, which states that the userbase for strong cryptography declines by half with every additional keystroke or mouseclick required to make it work. Think about that when you’re designing tools.
December 31, 2008
Ellison’s Law
Mac OS X Redesign: Feedback for “Hold Keys”
To prevent particularly bad slips (physical, not cognitive, mistakes), Apple makes certain keys hold keys. That means you have to hold them down for a while before they do their thing, unlike any other button that you just tap to use. This prevents accidentally engaging the hold keys, because a quick tap isn’t enough to trigger them. Unfortunately, it causes major problems for users. Apple could fix things by simply adding 3 words to the key-pressed-indicators they already use, and displaying it immediately.
The eject key is a hold key on MacOSX 10.4.9+. It’s a pretty bad thing to accidentally activate, because it takes several seconds to put a physical disk back into a tiny slot . By comparison the most common slips (typos), can be corrected in a split-second with 2 keystrokes(delete + the right letter). The eject key is located just above the delete key (which behaves like backspace on other computers), and right next to F12, which by default is mapped to Dashboard. Both of these keys are relatively high traffic, so it’s a sure bet that many a slipped finger will tap the eject-key. Making the eject-key a hold key prevents accidental taps, because a tap isn’t enough to trigger it.
caps lock on new keyboards is a hold key to turn on (but not off). Anything that makes caps lock harder to engage is great, since there’s no good reason to have a caps lock key anyway.
But there is a big problem with what Apple has done here. There isn’t any indication that hold keys are special. Worse, if you try to use one the way you use every other button on the keyboard, mouse, or computer — by tapping them – nothing happens. It’s like the hold keys are broken. here’s a video showing how confusing the eject key is.
One of the first things I noticed after updating Mac OS X Tiger to 10.4.9 was that my CD eject key didn’t seem to work anymore
Unfortunatly, that is a common reaction.
All hold keys should give immediate feedback when tapped, and also indicate that they need to be held down to trigger their action. Macs already flash an translucent eject indicator when the eject key’s action is performed:
Immediately displaying the following indicator, and pulsing the symbol when the action is triggered does everything we need:
This is just a quick mock-up to get the idea across, it has a lot of flaws.
Unlike the eject symbol, the text has no drop shadow — this makes it less busy, and easier to read; but arguably unaesthetic.
The text is in all lowercase, because all words on Apple keyboards are in all lowercase. The idea is that it more closely associates the instructions with the keyboard. It’s probably a mistake, since it does not follow the capitalization rules for Mac OS X, but it made sense to me at the time.
The text also should have a stronger border, so it will show up clearly no matter what it is displayed over. And it should be bigger. And in a better font.
But hopefully this is enough to get my idea across.
December 30, 2008
Different Symptoms of Different Eyestrain
(Sheedy, Hayes, & Engle) found that reading with difficult environmental conditions such as upward gaze, glare, flickering light, or small text caused the participants to report symptoms of burning, irritation, and dryness.
While reading with internal problems like having to turn your eyes inward, astigmatism, and stress on the focusing lens caused the participants to report ache, strain, and headache.
Sheedy, J.E., Hayes, J., & Engle, J. (2003). Is all Asthenopia the Same? Optometry and Vision Science, 80 (11), 732-739.
Via fontblog.
December 29, 2008
Thread Local Storage in Cocoa
[[NSThread currentThread] threadDictionary]
gives you an NSMutableDictionary
that you can use for thread-specific storage.
December 28, 2008
Fast Enumeration In Objective-C 1.0
I have used ForEach.h to do “Fast Enumeration” in Mac OS X 10.4 “Tiger”, without any problems. You must set the “C Language Dialect” in Xcode to C99 for it to work. Credit to Michael Tsai for the code, you can find other implementations of it on his website.
With ForEach.h you can do:
#import "ForEach.h"
foreach(thing, collection) {
/*do stuff with thing*/
}
foreacht(NSString, name, allNames)
;//name is typed as an NSString*
With a large collection, the foreach
macro should be faster then using NSEnumerator
or objectAtIndex:
, because it calls the nextObject
function directly, without going through Objective-C’s message sending. I have not benchmarked it, because I haven’t had a reason to optimize the mechanics of my for-loops, so I don’t know by how much. But it should give you the fast in Fast Enumeration.
If you can’t use Objective-C 2.0’s Fast Enumeration (requires Leopard or, iPhone), then I highly recommend ForeEach.h.
Open Radar
Open Radar is a place for developers to share bug reports they have filed with Apple. Please post bugs there after you have filed them with Apple.
Understandably, third-party developers don’t have access to Apple’s bug database.
But that means they can’t see bugs someone else has filed, hence Open Radar. (Update 2009-01-04: to give you an idea of how difficult this can be, recently Apple closed some of bugs I filed as “Duplicate”, but I can’t read the original bug report they are tied back to. So I have no way of knowing what the status of the fix is, if they have a work around, or even if it’s already been fixed.)
Amazingly “(it was) less than 24 hours from idea proposition to (Open Radar) being built, deployed, and used.” That should give you an idea of how useful this can be.
Open Radar is still nascent. There’s no RSS feed for example. But with community involvement, it can only get better.
I’ve filled my bugs, have you?
Bug: @encode(long double)
UPDATE 2010-08-16: I ran a test today, on Mac OS X 10.6.4 (i386), and the issue has been resolved, @encode(long double)
evaluates to "D"
. I’m not sure when this change happened, or what platforms it effects.
@encode(long double)
returns the same string, "d"
, as @encode(double)
, at least on i386, Mac OS X 10.5.6 / 9G55. But a long double
and a double
are not identical:
double aDouble = M_PI;
long double aLongDouble = M_PI;
NSLog(@"sizeof(aDouble) = %d, sizeof(aLongDouble) = %d",
sizeof(aDouble), sizeof(aLongDouble));
NSLog(@"aDouble = %f", aDouble);
NSLog(@"aLongDouble printed as a double (%%f) = %f", aLongDouble);
NSLog(@"aLongDouble printed as a long double (%%Lf) = %Lf", aLongDouble);
sizeof(aDouble) = 8, sizeof(aLongDouble) = 16
aDouble = 3.141593
aLongDouble printed as a double (%f) =
-88796093704928900002674917893032219152220160.000000
aLongDouble printed as a long double (%Lf) = 3.141593
I haven’t tested another configuration. TYPE_LONGDOUBLE_IS_DOUBLE
in ConditionalMacros.h is 1 under __ppc__
, so this might not be a problem on PowerPC.
Submitted as radar://6468314.
December 26, 2008
Which Side To Use
If you are ambidextrous, feel smug and ignore this.
Keep your keys, wallet, or whatever opens doors, in your weak-side pocket.
This is a bit counterintuitive. I used to keep them in my strong-side pocket for years. It’s natural to use your strong hand to unlock a door or buy a sandwich. But it causes problems when you need to open a door while carrying something awkward/heavy (say groceries, a cat, etc).
You should be carrying awkward things with your strong hand. It’s safer and easier. But when your strong-hand is full, it’s hard to get keys from your strong-side pocket. Meanwhile, keys in your weak-side pocket are still easy to employ.
I’m not especially dexterous, but in my experience, using my weak hand to unlock something hasn’t been a problem. I expected it to be harder, but honestly it hasn’t been perceptibly more difficult. Keeping keys in my weak-side pocket has been nothing but good.
Mobile-phones, pocketknives, cameras, PDAs, etc. should be in your strong-side pocket.
You should be using your strong-hand when you use them, but more importantly you (generally) don’t need to use them while carrying something. Cutting stuff while carrying a bag of groceries is a bad idea, for example.But, anything you need to use while your strong hand is full should still live on your weak side with your keys. Phones make handy flashlights, for example.
Hold drinks with your weak hand.
I’ve been trying to train myself to do this for years, and I haven’t been able to.
The theory is that your weak hand is plenty up to the task of bringing a glass to your mouth (if it isn’t, you shouldn’t be drinking!), and it’s useful to have your strong hand free. Plus holding a cold drink makes your hand cold and wet, which surprisingly isn’t cool when you need to shake with that hand. So holding drinks in your left hand = a better first impression.
Always Update the View From the Main Thread
I wish I’d read this years ago:
AppKit, the GUI framework, is not thread safe. In order for things to work properly, you (almost) always need to update GUI classes from the main thread
—Dave Dribin (slightly edited)
I’ve run into UI + threading problem before, but I’d just never seen this limitation of AppKit spelled out.
Dave’s article explains how to call code on the main thread better then I can.
December 22, 2008
Resources in Unit Tests and Other Frameworks
To load a resource inside a unit test or other bundle, do:
NSBundle *unitTestsBundle = [NSBundle bundleForClass:[self class]];
NSString *pathToResource = [unitTestsBundle pathForResource:name ofType:fileExtension];
[NSBundle mainBundle]
points to the bundle for the current executable, so it’s handy in an application (where it will point to your .app bundle). But since unit tests are loaded into another program or test-harness to run, it’s not appropriate to use it in a unit test.