iPhone 4: <i>No Italics!</i>

This sounds crazy, but seems to be true: +[UIFont italicSystemFontOfSize:] simply returns a regular non-italic font on iPhone 4 hardware.

The release notes state:

iPhone 4 uses a different system font than earlier devices. References to the Helvetica font in nib files will be decoded as the system font on these newer devices.

The “different system font” appears to be Helvetica Neue, for which there is no italic version included.

Since you’ll always want to use the system font for your user interface, what this means is: no italics for your UI.

This absolutely must be intentional and not a bug. Changing the system font on a new iPhone model for which a primary new feature is better font rendering, is a huge deal.

I’m not complaining about it, I think it’s a fine decision, but also extremely interesting, don’t you think?

How to check out new music on Rdio

1) First, search for an artist you’re interested in:

Now scroll down to “Popular Songs.” See that Play button?

2) That’s the one. Press that. Press it.

3) Now you’re listening to some awesome music. How easy was that?!

For extra fun, share it with your friends:

Improvements to Google Wave Notifier

Download the notifier now

I tried out the Unofficial Google Wave Notifier and liked its functionality, but wasn’t thrilled with the UI:

So I made some changes:

The icon glows blue when you have unread waves, inspired by Tweetie for Mac:

I also added a selector for choosing which browser the Notifier opens Google Wave in when you click things.

Creating this selector in Cocoa on OS X was a lot more involved than I thought going in. But at least it’s not Windows, which would have been 10 times more painful.

I also refactored the notifier to be fully asynchronous so it doesn’t block the main thread and is always responsive.

Check it out on Github.

There, I fixed Xcode—You’re Welcome.

Download xcode-auto-assistant now

In my last installment, I discussed Xcode’s frustrating implementation of code completion.

I’ve now taken matters into my own hands.

It turns out Xcode has an (undocumented) plugin system. And it also turns out that this guy created a really fantastic plugin for Xcode that automatically inserts a matching opening bracket ‘[’ when typing the closing bracket ‘]’.

Now, it turns out Apple added this bracket-insertion feature on their own, possibly being inspired by this, so the plugin is now just reference material.

Really useful reference material for doing what I want to do.

I’ll save the nitty-gritty details of how the plugin works for a later post (or just browse the source). Let’s just say that we have access to keystrokes as you type them in Xcode. How would we use that to achieve automatic completion list display?

Take 1: Popup all the time!

The most useful behavior, it seems, is for the popup list to appear as soon as you type a reasonable character that can be completed, such as an alphabetical character. Here we’ll type ‘u’ because we want UIViewController.

So that’s the first thing I implemented. Listen for alphabetical character, popup the list.

The problem turns out to be that the list takes “a while” to appear, because we’re in Objective-C which is still C and the number of legal symbols you can type in a particular location is immense. I mean look at that tiny scrollbar! There’s all manner of detritus in there like u_quad_t and UIKIT_STATIC_INLINE.

You might think, no problem, I’ll just ignore the popup and keep typing because the list will narrow itself down as I go. But, in practice, it turns out to be extremely annoying because you can’t type small words like “if” and “for” without the popup list slowing you down.

Examine our options

I imagine that Apple encountered this same problem, and it seems the way they addressed it was by analyzing the number of items that would match and only giving you a suggested completion if the number of possible matches is small.

This is why, with Apple’s completion, you must type “nss” before it will automatically suggest something like “NSString”. If you just type “ns” you can sit there forever and it’ll never suggest anything. But if you type “cl” it might suggest “CLLocation” because there aren’t a lot of other things starting with “cl”.

My beef with this approach is that it’s unpredictable. How do I know how many letters I’m supposed to type before I can press enter and move on?

Take 2: Smart delay

The solution turned out to be surprisingly simple. Display the list after typing any alphanumeric character, but with a delay proportional to the number of characters in the word entered thus far. On the 4th character and beyond, the list always appears immediately.

This way you can type “uivi[enter]as fast as possible and you get UIViewController (depending on your typing history, but this is intuitive).

By the time you get to the 4th character, the list is almost always reasonably small and therefore much more helpful.

If you just type “u” and forget what you were doing, we’ll wait about 0.4 seconds before presenting the list to help you.

More importantly, you can type “for (int i = 0…” at normal typing speed without the popup appearing at all, and once you get stuck on something you’ll pause naturally and only then will the list appear.

Extras

Of course, you don’t want the list appearing on just any alphanumeric character: If you’re writing a string or a comment, the list isn’t going to help you. So the plugin does some extra work to detect those situations. It’s not a full-on lexer but it seems to work 99% of the time.

Additionally, if you type a period ‘.’ to access a struct member or ObjC property, the list always appears immediately.

One last neat feature: When you type a semicolon, it will be automatically moved to the end of the line as necessary. I don’t know about you, but I often find myself in this kind of situation:

…having just typed a method name and needing to cap off the line with a semicolon. Normally I’d have to go find the right arrow key first, but with the plugin you just type ‘;’ and it puts it in the right place.

Pretty cool!

Try the plugin here.

Code Completion and XCode

Update: I wrote a plugin to address these issues.

The newish mac app Espresso contains a great (and uncommonly beautiful) implementation of code completion.

It goes like this. Say you’re editing a CSS file:

That’s a nice blue background, but you also want a border. You start by typing the letter “b”:

Since Espresso knows that there are many possible options that start with “b”, it presents them to you in this lovely but minimal popup. You can use the arrows and press enter to select something from the list. Or, you can pretend the list never appeared and keep typing. Once you type enough to eliminate all other options, the list disappears and you’re left with a more standard OS X “completion” highlight. You can still press enter to accept this last suggestion.

The two things I want to emphasize about this workflow are:

  • It’s predictable. I trust Espresso to always give me all possible relevant options after each keypress. And I know that I just press enter to accept and move on.
  • It’s useful. Whenever there are multiple options, they are presented to me in the list, and the list appears automatically when needed.

Predictable

XCode goes like this. Say you’re writing some Objective-C:

We need to make a new instance of UIViewController, so we begin our journey of typing the class name.

XCode does nothing so far. We know it has a set of suggestions to help us—if you press ESC now, you’ll see a nice list of all the classes starting with “UI”. But for some reason it’s decided not to jump in yet. (Note: My Code Sense delay is set to Immediate). We press on, typing “v”:

Ah ha, there it is! Clever XCode! That’s what we want—so we’ll press enter:

Curious. It has only partially completed the word. See how before, only the ‘i’ was highlighted? This is a (newish?) feature of XCode. It turns out there are a few other classes starting with the prefix “UIVi” and it doesn’t want to assume that I want something starting with UIView and not, say, UIVideoEditorController which I never knew existed until just now.

At this point if I press enter again, it will go ahead and fill in the rest of the word.

So it eventually gave me what I wanted. But here’s a wrinkle: if I would have typed “uivi” myself first, it would have suggested UIViewController just the same, but in that case it would have completed the entire word when I pressed enter.

The problem here is that XCode is not predictable. When I’m typing code, my brain is moving faster than my fingers. I can decide to type [[[UIViewController alloc] init] autorelease] a hell of a lot faster than I can actually write it. And my brain can’t move on to a more interesting problem until it can give my fingers a known sequence of keys to press. XCode’s completion is a different back-and-forth conversation with the editor every time. How do I get it to finish UIViewContoller? Do I press enter once, twice, three times? It depends how many characters I typed first, which also depends on factors like XCode tailoring its suggestions based on my code history.

Useful

Here’s another example. Let’s set the frame of our new controller’s view, by first declaring a new CGRect:

Now here I’ve typed the letters cgrect just like that, and XCode hasn’t suggested anything at all. Maybe I have to type more than 6 characters before XCode jumps in? (Nope, that’s not it.)

OK well, I’m done typing now, so I have to fixup this cgrect by turning it into a real CGRect with proper caps. Maybe XCode can help with this? I’ll press ESC.

OK, so I got lucky, it happens to be the 2nd item in the list. (If this list was sorted alphabetically, as it is by default, CGRect by itself wouldn’t even be on it). But still, I’ve written an exact match, shouldn’t that be what’s selected by default instead of CGRectInset? Now I have to fiddle with arrow keys and scrolling and by this point I could have just typed out CGRect myself with proper carpal-tunnel-inducing capitalization and skipped all this business.

It gets worse

These are just two examples out of many. In fact, XCode’s completion is so unhelpful that I can only assume the engineers at Apple never have it turned on, and maybe just code everything in Vim anyway. To me, it feels like the sort of feature that was built to “satisfy” demand from non-Apple developers. Look, fine, we’ll give you your ‘completion’, you Microsoft-coddled sissies, now please go away and let us work on OS X 10.7 already!

It’s just a bit sad for me, because I have tasted the sweet nectar of real, predictable, useful code completion, and it is wonderful and productive. This isn’t an intractable problem! It just needs some more TLC.

If you agree with my findings, I encourage, nay, command you to go fill out a bug report with Apple (they really do read these).

I have also reposted the issue on Open Radar.

Transport!

I finally sat down and published Transport, a little app I’ve been using for quite a while to send files and screenshots and such. Mostly screenshots, because it turns out this is incredibly useful when it only takes one keystroke. Communicating via images is sometimes a zillion times easier than typing 1000 words and all.