Skip to content

Archive for

5
Nov

Review: Raving Fans

The first thing I noticed about Raving Fans was how short it is. 132 pages of large fonts and lots of whitespace makes the book appear longer than it is. Many pages are more than half blank. The authors use a parable to help explain their suggestions and, without it, the book could probably be condensed to just a few pages.

That said, the content of the book is good. The basic outline is:

  1. Decide what you want.
  2. Discover what the customer wants.
  3. Deliver the vision plus one percent.

Alliteration aside, I would rephrase these points as:

  1. Envision the perfect customer experience and compare it to reality.
  2. Ask customers for feedback and adjust the vision as appropriate.
  3. Promise only what can be consistently delivered and then make slow, stead improvements.

The most helpful part of the book was the point about envisioning the completed picture before talking with customers, and then using their feedback to make refinements. This idea meshes well with other things I’ve read. It is very hard for normal people (those who don’t spend all day thinking about your product or service) to imagine what is possible. So giving them a context within which to make comments is very helpful.

One bad thing is the examples and situations in the book often seem contrived or unrealistic. I would have liked to see an appendix with references upon which the situations in the book are based. Otherwise, it feels like the authors took their theory and just made up examples to help explain it without any supporting evidence from a real company where their theory had been put into practice.

Overall, I don’t think I’ll be rereading Raving Fans. It’s light on content and most of what I learned can be summarized in one or two short paragraphs.

26
Oct

Original Inspiration for the iPhone Maps Application

I am 100% sure that this Dilbert comic from 1990 was Steve Jobs’ original inspiration for creating the iPhone with its famous Maps application:

Dilbert from May 10, 1990

You knew that Dilbert was over 21 years old, right? (I didn’t. :)

21
Oct

How to Launch a Privileged Process on OS X

For security reasons, Apple recommends that GUI applications should never run with the privileges of the root user. GUI applications normally load several types of plugins and input managers automatically. If a malicious plugin was installed then it could cause security problems when the privileged application was launched.

In addition, system services that run with the privileges of the root user (such as launch daemons) need to avoid using certain technology frameworks provided by Apple. These frameworks are not safe to use in a service that runs with the privileges of the root user.

If you need your GUI application to do something that requires root privileges, Apple recommends you split your application into two parts. First, create a GUI that runs as a normal user. Then when you need to do something with root privileges, you launch a separate helper process or tool. Splitting your application avoids security holes while keeping things very easy for your users.

Two Steps

Launching a privileged process is done in two steps:

1) Request authorization. The operating system will ask the user for permission to run a privileged process. The user will need to enter an administrator’s username and password.

#import <Security/Security.h>

OSStatus PreauthorizePrivilegedProcess(AuthorizationRef *authRef) {
    AuthorizationItem item = { kAuthorizationRightExecute, 0, NULL, 0 };
    AuthorizationRights rights = { 1, &item };
    AuthorizationFlags flags = kAuthorizationFlagInteractionAllowed | kAuthorizationFlagExtendRights | kAuthorizationFlagPreAuthorize;
    return AuthorizationCreate(&rights, kAuthorizationEmptyEnvironment, flags, authRef);
}

2) Launch the process. If the user authenticates correctly, you can use the authorization reference created above to launch the helper process.

OSStatus LaunchPreauthorizedProcess(AuthorizationRef *authRef, NSString *path) {
    OSStatus status = AuthorizationExecuteWithPrivileges(*authRef, [path UTF8String], kAuthorizationFlagDefaults, NULL, NULL);
    AuthorizationFree(*authRef, kAuthorizationFlagDestroyRights);
    return status;
}

Please note that the authorization reference created in the first function is released in the second function. If you want to launch several privileged processes in a short amount of time, you can comment out this line and and release the reference on your own afterwards.

Some of Apple’s sample code (and other examples) has an extra step where they copy the authorization reference. This is only necessary if you have a previously created authorization reference that you want to add elevated privileges to.

Just One Step

If you don’t need to update your GUI between these two steps, then both actions can be combined into one step.

#import <Security/Security.h>

OSStatus LaunchPrivilegedProcess(NSString *path) {
    AuthorizationRef authRef;
    OSStatus status = AuthorizationCreate(NULL, kAuthorizationEmptyEnvironment, kAuthorizationFlagDefaults, &authRef);
    if (status == errAuthorizationSuccess) {
        status = AuthorizationExecuteWithPrivileges(authRef, [path UTF8String], kAuthorizationFlagDefaults, NULL, NULL);
        AuthorizationFree(authRef, kAuthorizationFlagDestroyRights);
    }
    return status;
}

I consider this code to be in the public domain. Please feel free to copy and paste. And let me know if you find any problems or have suggestions.

4
Aug

How To Type Curly Quotes In Mac OS X

Mac OS X has an easy way to type “curly” quotes and apostrophes instead of "straight" versions. I used both versions in that sentence to show the difference. Here is a bigger version to make the distinction more visible:

Many people think “curly” quotes look better than "straight" ones.

You can use the following keyboard shortcuts to type a single or double curly quote:

  1. Single quote open (‘) — option ]
  2. Single quote close (’) — shift option ]
  3. Double quote open (“) — option [
  4. Double quote close (”) — shift option [

However, I think it makes more sense to use [ and ] for open and close versions instead of the shift key. I found myself constant typing “mismatched‘ quotes. I also wanted to use the shift key for double quotes since that’s how the normal keyboard button works.

  1. Single quote open (‘) — option [
  2. Single quote close (’) — option ]
  3. Double quote open (“) — option shift [
  4. Double quote close (”) — option shift ]

Since OS X supports custom key bindings, I looked for a way to fix this. The trick is to create a file called DefaultKeyBinding.dict in the KeyBindings folder inside your Library folder. You can use this file to override the default key bindings for most applications.

Here are my changes. Please feel free to copy the settings below and save them to your own computer. You may need to create the KeyBindings folder if it isn’t already there.

/*
 Updates Apple's default keybindings for curly quotes.
 See http://www.danandcheryl.com/2010/08/how-to-type-curly-quotes-in-mac-os-x

 Save this file here:
 /Users/<name>/Library/KeyBindings/DefaultKeyBinding.dict
*/
{
    "~[" = ("insertText:", "‘");
    "~]" = ("insertText:", "’");
    "~{" = ("insertText:", "“");
    "~}" = ("insertText:", "”");
}
3
Aug

Someone Cool Wants To Buy My Car

On my way to work today, while waiting at a stop light, a guy in the car next to me leaned out of his window, smiled and signaled that he wanted to talk. I took off my sunglasses, pulled my earphones out and rolled down my window.

“Want to sell your car?” he asked. I admit to being a little taken aback. My car isn’t for sale. He was in a van obviously owned by his employer with another guy driving. He’d seen my car and had the guts to ask a complete stranger waiting at an intersection if he wanted to sell the car he was driving.

“Sure,” I smiled. I don’t really want to sell my car. Not for market value anyway. It’s too much hassle to replace. But if he’s really interested, maybe I could get a good deal. I suppose he already knew how awesome an old Honda Civic can be.

“How much?” he wanted to know. “I have no idea,” I shrugged. He asked how many miles it had (about 200,000) and got my phone number as the light changed.

“I’ll call you,” he promised as we drove off in different directions. I guess I’ll find out. Meanwhile, I am taking a look around my life to see if there is something I want that I haven’t had the guts to ask for.

27
Jul

Family Pictures Summer 2010

We took the kids down to get their pictures taken recently. We ordered digital copies of the pictures this time because I’m too lazy to scan them into the computer. They turned out great.

Kid collage

Kid collage

Kid collage

12
Jul

Review: Good To Great

A few months ago, I joined a company called Imagine Learning that makes software to teach kids English. One thing I love about the company (it’s my second time working for them — yeah, long story :-) is that they choose a book each year, purchase a copy for every employee, and encourage them to read it. Last year’s book was Good To Great by Jim Collins which I was asked to read during my first few weeks on the job.

In short, the book is really good. The principles can be applied in non-work settings, to any group of people working toward a shared objective. The biggest downside is that, to be useful, those principles must be adopted by the leader of the group. The CEO of Imagine Learning is an advocate, which is one of things I like best about the company.

The principles, in the order in which they need to be applied, are:

  1. Leaders who are ambitious for the success of the company over themselves.
  2. Getting the right people into the company (and the wrong ones out) before making other decisions.
  3. Honest assessment of the present combined with optimism about the eventual future.
  4. Exclusive focus on a single idea at the intersection of passion, economics and being the best.
  5. Freedom and responsibility within a disciplined system.
  6. Selective use of technology to accelerate success.

Some excerpts should help illustrate why I like the book so much.

You must maintain unwavering faith that you can and will prevail in the end, regardless of the difficulties, AND at the same time have the discipline to confront the most brutal facts of your current reality, whatever they might be. (p13)

The purpose of compensation is not to ‘motivate’ the right behaviors from the wrong people but to get and keep the right people in the first place. (p50)

Put your best people on your biggest opportunities, not your biggest problems. (p58)

The entire management team would lay itself open to searing questions and challenges from [people] who dealt directly with customers. (p72)

Focusing solely on what you can potentially do better than any other organization is the only path to greatness. (p100)

The purpose of bureaucracy is to compensate for incompetence and lack of discipline. (p121)

Mediocrity results first and foremost from management failure, not technological failure. (p156)

If you want to build an enduring and financially successful company, I don’t know of a better place to start than Good To Great.

28
Jun

How to Check the System Idle Time Using Cocoa

UPDATE: Aleksandar Sabo wrote a brief explanation of how this code works.

There is sample code on the Internet for programmatically checking the system idle time using IOKit and Cocoa (see here, for example). However, most of the examples seem overly long (see Paul Graham’s Succinctness is Power). The code below works in Tiger/10.4 and later and is about as concise as I can make it while still handling errors properly.

#include <IOKit/IOKitLib.h>

/**
 Returns the number of seconds the machine has been idle or -1 if an error occurs.
 The code is compatible with Tiger/10.4 and later (but not iOS).
 */
int64_t SystemIdleTime(void) {
    int64_t idlesecs = -1;
    io_iterator_t iter = 0;
    if (IOServiceGetMatchingServices(kIOMasterPortDefault, IOServiceMatching("IOHIDSystem"), &iter) == KERN_SUCCESS) {
        io_registry_entry_t entry = IOIteratorNext(iter);
        if (entry) {
            CFMutableDictionaryRef dict = NULL;
            if (IORegistryEntryCreateCFProperties(entry, &dict, kCFAllocatorDefault, 0) == KERN_SUCCESS) {
                CFNumberRef obj = CFDictionaryGetValue(dict, CFSTR("HIDIdleTime"));
                if (obj) {
                    int64_t nanoseconds = 0;
                    if (CFNumberGetValue(obj, kCFNumberSInt64Type, &nanoseconds)) {
                        idlesecs = (nanoseconds >> 30); // Divide by 10^9 to convert from nanoseconds to seconds.
                    }
                }
                CFRelease(dict);
            }
            IOObjectRelease(entry);
        }
        IOObjectRelease(iter);
    }
    return idlesecs;
}    

I consider this code to be in the public domain. Please feel free to copy and paste. And let me know if you find any problems or have suggestions.

18
May

How to Print a PDF File Using Cocoa

UPDATE 2014-03-13: @robwithhair created a command-line tool for printing PDF files based on this code which shows some additional options.

Mac OS X is well known for its great support for PDF files. You can create a PDF file from anything you can print. I thought that using Apple’s PDFKit framework would make it easy to program a way to print an existing PDF file. That turned out not to be the case.

Sending a file to a printer using the lp command is easy. However, this approach does not work for PDF files formatted for landscape printing. You can specify landscape orientation, but I wanted a way to detect the orientation automatically.

PDFKit has a PDFView object that has a printWithInfo:autoRotate: method. However, adding a PDFDocument to a PDFView and telling it to print doesn’t work. I eventually stumbled onto the fact that PDFDocumenthas a secret method that makes printing easy. So here is the code:

#import <Quartz/Quartz.h>

- (void)printPDF:(NSURL *)fileURL {

    // Create the print settings.
    NSPrintInfo *printInfo = [NSPrintInfo sharedPrintInfo];
    [printInfo setTopMargin:0.0];
    [printInfo setBottomMargin:0.0];
    [printInfo setLeftMargin:0.0];
    [printInfo setRightMargin:0.0];
    [printInfo setHorizontalPagination:NSFitPagination];
    [printInfo setVerticalPagination:NSFitPagination];

    // Create the document reference.
    PDFDocument *pdfDocument = [[[PDFDocument alloc] initWithURL:fileURL] autorelease];

    // Invoke private method.
    // NOTE: Use NSInvocation because one argument is a BOOL type. Alternately, you could declare the method in a category and just call it.
    BOOL autoRotate = YES;
    NSMethodSignature *signature = [PDFDocument instanceMethodSignatureForSelector:@selector(getPrintOperationForPrintInfo:autoRotate:)];
    NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];
    [invocation setSelector:@selector(getPrintOperationForPrintInfo:autoRotate:)];
    [invocation setArgument:&printInfo atIndex:2];
    [invocation setArgument:&autoRotate atIndex:3];
    [invocation invokeWithTarget:pdfDocument];

    // Grab the returned print operation.
    NSPrintOperation *op = nil;
    [invocation getReturnValue:&op];

    // Run the print operation without showing any dialogs.
    [op setShowsPrintPanel:NO];
    [op setShowsProgressPanel:NO];
    [op runOperation];
}

I consider this code to be in the public domain. Please feel free to copy and paste. And let me know if you find any problems or have suggestions.

5
Apr

Cold Water Shaving

After reading about shaving with cold water, I’ve tried it several times over the last few days. It’s a much better experience for me.

Shaving with cold water seems like a hardship, a practice that must be endured in Spartan living conditions. After all, it’s wet shaving doctrine that a man must always shave with hot water. It not only feels nice, it softens the beard and supposedly gives you a more comfortable shave.

But what if that advice is wrong? What if it’s actually better to shave with cold water…?

Well, according to a bunch of authors in the 19th century, cold water shaving is indeed superior to shaving with hot water.

The biggest improvements for me were:

  1. Much easier to cut my hair. I have a smoother shave with one pass than I was getting with two.
  2. Getting fewer nicks and cuts on my face.

I have to admit, I’m sold.