-[NSString drawWithRect:options:attributes:context:] doesn’t like NSBackgroundColorAttributeName

This works:

NSDictionary *attributes = @{
  NSForegroundColorAttributeName:[UIColor blueColor]
};

[@"Hello" drawWithRect:CGRectMake(20, 20, 50, 50) options:0 attributes:attributes context:nil];

This doesn’t:

NSDictionary *attributes = @{
  NSForegroundColorAttributeName:[UIColor blueColor],
  NSBackgroundColorAttributeName:[UIColor redColor]
};

[@"Hello" drawWithRect:CGRectMake(20, 20, 50, 50) options:0 attributes:attributes context:nil];

No text appears, at least not on iOS 7.0.4. If the NSStringDrawingUsesLineFragmentOrigin option is included (i.e. multi-line text enabled), the text appears with the background color as expected.

How to Generate iOS Code-Signing Certificates Using (Mostly) the Command Line

Generate the key pair:

openssl genrsa -out jonah.key 2048

Generate the certificate signing request (CSR). Apple ignores the subject, so we leave it blank:

openssl req -new -subj / -key jonah.key -out jonah.csr

Now submit the CSR to the Apple Developer site. It will give you a certificate in DER format. We need to bundle this certificate with the key pair before we can add it to the keychain where Xcode can access it. Assume the certificate has been named jonah.cer. First convert it from DER to PEM:

openssl x509 -inform der -in jonah.cer -out jonah.pem

Then package the key pair and certificate into a single PKCS #12 file. You’ll have to type an “export password.”

openssl pkcs12 -export -inkey jonah.key -in jonah.pem -out jonah.p12

Finally, launch Keychain Access and import the PKCS #12 file with File > Import Items. Keychain Access will prompt you for the password you chose in the last step. If you’re really a command-line die-hard, you can import like this:

security import jonah.p12 -k "/Users/jonah/Library/Keychains/login.keychain"

One more tip: You may want to give the private key a friendly name in Keychain Access, as it’s assigned what looks like a random hex string by default.

A Somewhat Hypocritical Post on the Menace of Hashtags

I saw someone write “#jealous” instead of “jealous.” Why? I guess one reason is that the writer is worried about laying his feelings bare, so he’s encasing his comment in a thin shell of humor. (Hashtags are nerdy; the irony of such a mundane hashtag; etc.) Might also be an attempt to be clever or different, albeit one that’s more than played. But the theory I like most involves the same phenomenon I wrote about in a post on the word “metastasize.” In that post, I tried and failed to derive the etymology of the word:

My silly theory demonstrates the rise of a colloquial sense of meta meaning “self-referential” as in metadata, metasearch, and “that’s so meta.” In this age of instant photos, check-ins, status updates, and countless other ways of symbolizing our own lives, I’m not surprised that this form invaded my brain and crowded out the good old Greek.

Self-reference: that’s the essence of a hashtag. It’s a bit of meta-data in the data itself. The writer’s not content with one level of meaning; he also wants to comment on his first thought, to assign it a category or suggest membership in a trend. Whether the poster of “#jealous” knew it, I think he had been gripped by this impulse. He didn’t just say “I’m jealous”; he also said, “There are other people like me.” The second part is a defensive move: It asserts the appropriateness of his comment and suggests that his emotion, while unattractive, is not uncommon.

To me, the trend toward self-reference isn’t a good one. Most of the artifacts I listed in my prior post—check-ins, status updates, etc.—are redundant. They are, frankly, a waste of everyone’s time. More importantly, they separate us just a bit from the heart of the matter. Instead of immediately understanding the poster’s feelings, we have to parse the hash, consider the second level of meaning, and discard it as empty irony or self-defense. If repeating this procedure encourages us to wrap our own thoughts in reference, the trend snowballs, and instead of a more “open and connected” world, we’re left with indirection and separateness.

In “The Image,” Daniel J. Boorstin lamented the proliferation of “pseudo-events”: contrived happenings such as press releases that exist only to be reported. He worried that pseudo-events might crowd out real, spontaneous events, leading us to lose touch with the truth. “#jealous,” then, might be called a pseudo-thought. Its menace is that we lose touch with each other.

The NYT Overstated Steve Ballmer’s Failure

Nick Wingfield of the NYT writes that “[Microsoft's] stock has lost 43% in value” since Steve Ballmer became CEO. That’s technically correct: The split-adjusted share price is 43% lower than it was on January 13, 2000, when Ballmer took over. But this measure—the change in share price—is a poor indication of Ballmer’s performance because it neglects dividends. Microsoft has paid $7.07 per share in dividends since it issued its first one in 2004, under Ballmer. An investor who reinvested these dividends would have lost not 43% but 24%—a significant difference.

Sometimes I Hate Living In This Fucking City

Sometimes I hate living in this fucking city. All day I deal with little impositions—the incessantly barking dog, the delivery guy riding the wrong way in the bike lane, the truck idling and belching fumes, the ice cream man playing that cloying music on repeat. All of these things are not just inconsiderate; they’re also minor violations of the law. But you deal with it because it’s New York, where anything goes. And you have no recourse anyway. The cops have better things to do.

That’s why I felt wronged when, tonight, four cops and a squad car devoted half an hour to writing me a summons for riding my bike on the sidewalk. When I asked them to consider the situation—I rode on an empty sidewalk for one block, from my street to the pizza shop, so as to avoid riding the half mile around the block—one of them responded, like a soldier, “I just do what I’m told,” and the other threatened me: “Keep talking and you’ll make it worse.”

Give me a break. I spent the morning riding lawfully to the post office to mail in my NYC taxes, and I’m not paying for the cops to police minor infractions with no victims. Today’s attack in Boston makes my complaint seem petty, sure, but the heroism of Boston’s first responders makes New York’s brand of police work seem all the more absurd. Either enforce all of it—the noise code, the idling prohibition, jaywalking, “don’t honk,” the $250 fine against dog poop—or leave us alone.

GKMatch Delivers Queued Messages When Its Delegate Is Set

static BOOL ready = NO;

// GKMatchmakerViewControllerDelegate
- (void)matchmakerViewController:(GKMatchmakerViewController *)viewController didFindMatch:(GKMatch *)match {
    match.delegate = self;
    ready = YES;
}

// GKMatchDelegate
- (void)match:(GKMatch *)match didReceiveData:(NSData *)data fromPlayer:(NSString *)playerID {
    NSAssert(ready, @"Not ready!");
}

This code will fail intermittently because GKMatch delivers queued messages when its delegate is set—not, say, the next time through the run loop.

Suppose, for example, that Alice’s game starts up faster than Bob’s. Alice starts sending messages, and Bob receives one before matchmakerViewController:didFindMatch: is invoked. Bob hasn’t set the GKMatch delegate, so Game Kit queues the message. Later, when Bob does set the delegate, Game Kit immediately calls match:didReceiveData:fromPlayer:. Bob isn’t ready, and the app asserts.

To fix the problem, we can swap the two statements in matchmakerViewController:didFindMatch:.

I Tried to Transfer a File Named “amélie” from Mac to FreeBSD

I transferred a file from Mac to FreeBSD and saw this surprising result:

mac$ ls
amélie
mac$ scp * freebsd:
mac$ scp freebsd:amélie .
scp: amélie: No such file or directory

After some research, I determined that Mac OS stores certain filenames differently than other OSes. In particular, it normalizes UTF-8 filenames in the canonical decomposition normalization form. What this means is that the file system represents things like “é” with two characters, the letter and the diacritic:

mac$ echo amélie | hexdump -C
00000000  61 6d c3 a9 6c 69 65 0a                           |am..lie.|
00000008
mac$ touch amélie
mac$ ls | hexdump -C
00000000  61 6d 65 cc 81 6c 69 65  0a                       |ame..lie.|
00000009

Notice the slight difference in the output of the two invocations of hexdump. In the first, “é” is represented by a single two-byte UTF-8 character (c3 a9). In the second, it is represented by three bytes encoding two characters: “e” (65) and an acute accent that combines with the prior character (cc 81).

Mac OS translates from the first representation to the second when you access the file. The problem is that FreeBSD and most programs do not. When I ran “scp freebsd:amélie .“, FreeBSD tried to find a filename matching the first byte sequence and failed.

Once you’ve let a decomposed filename sneak onto your FreeBSD file system, all sorts of strange things can happen:

freebsd$ ls | hexdump -C
00000000  61 6d 65 cc 81 6c 69 65  0a                       |ame..lie.|
00000009
freebsd$ rm amélie
rm: amélie: No such file or directory
freebsd$ touch amélie
freebsd$ ls -1
amélie
amélie

One of the most frustrating things is when you try to access such a file on a network share in the Finder. The Finder shows the file, but attempts to copy it fail silently or with an obscure error.

Luckily, there is an antidote to all these problems: Netatalk, the AFP server for *nix/*BSD systems. Netatalk normalizes filenames using the host system’s normalization:

mac$ ls | hexdump -C
00000000  61 6d 65 cc 81 6c 69 65  0a                       |ame..lie.|
00000009
mac$ cp * /Volumes/freebsd-via-netatalk
mac$ ssh freebsd
freebsd$ ls | hexdump -C
00000000  61 6d c3 a9 6c 69 65 0a                           |am..lie.|
00000008
freebsd$ rm amélie

I’ve never been so happy to see no output. The moral of the story is, when you transfer non-ASCII-named files from Mac to the outside world, always do so via Netatalk.

iPhoto May Hang on Startup if Your DNS Servers Return Addresses for Non-Existent Domains

Little Snitch reported that automountd was trying to send sunrpc calls to a strange domain when I started iPhoto. Then I noticed that iPhoto was taking a long time to start up, displaying the wait cursor (spinning pinwheel) for almost a minute. Hmm … had my computer contracted some malware?

Turns out, no. The problem was caused by curious iTunes behavior coupled with an annoying DNS server. When iPhoto 8.1.2 starts, it tries to mount IPHOTO.XML and PHOTO_CD (no idea why), and automountd tries to resolve these names to network addresses. Normally, this resolution fails and iPhoto moves on. In this case, however, my ISP was returning addresses for non-existent domains:

$ dig IPHOTO.XML @167.206.254.1 +short
67.63.55.3

(ISPs like to do this so that your browser will show pages full of ads when you type bad addresses into your browser. They don’t realize that this behavior, beyond being impolite, screws up programs that rely on sensible DNS responses.)

automountd was trying to send NFS pings to the resolved host and giving up after about 40 seconds. Hence the delay. I switched my DNS servers to Google’s Public DNS, and iPhoto started immediately.

But one mystery remained: Why did Little Snitch report a connection to some strange domain and not the IP address or IPHOTO.XML? A reverse lookup on 67.63.55.3 yielded nothing. I can only speculate that OS X uses a local DNS cache for reverse DNS resolution. Lots of domains (all non-existent ones) had resolved to that IP, and the cache somehow picked one. I found some evidence for this hypothesis by restarting the computer. Little Snitch then reported IPHOTO.XML and PHOTO_CD as expected, and a dump of the mDNSResponder cache revealed entries for both “domains.”

Objective-C Neophyte Deems Key-Value Coding Unnecessary

Couldn’t this be written without Key-Value Coding as follows?

- (id)tableView:(NSTableView *)tableview objectValueForTableColumn:(id)column row:(int)row
{
    ChildObject *child = [childrenArray objectAtIndex:row];
    return [child performSelector:NSSelectorFromString([column identifier])];
}

Given the dynamism of Objective-C, why is Key-Value Coding necessary here — or anywhere?