Obtaining your iOS Device Unique Device ID (UDID)

So you've got a friend who has written an iOS app and he or she wants you to beta test it. (Hint: if you're reading this, I'm that friend!) What do you need to do?

You need to provide that friend with your iOS device's "Unique Device ID" or UDID. Your friend can then generate a certificate that tells your device that it is allowed to run the beta app. You can drop this certificate and the app itself on iTunes and iTunes can then install the app on your device. All well and good but UDID's are long numerical strings and are a pain to find and type in anywhere. Apple provides an interface for getting them but it works a bit unusually and I thought it was worth writing some notes.

Here's an image of the Apple instructions. Everything you need to know is here but you have to read it carefully.

Finding  your iOS Device UDID

So here are step-by-step instructions:

  1. Launch iTunes.

  2. If you have Wi-Fi Sync enabled your device should already be in the sidebar. If you don't have Wi-Fi Sync turned on then you'll need to connect the device with a cable.

  3. Select the device in the sidebar and make sure you have the Summary Tab displayed. You'll probably see the Serial Number displayed.

  4. Click the Serial Number itself (or the text label that says "Serial Number") and it will toggle to displaying Identifier (UDID): and the actual UDID string.

  5. OK, this is the weird part. Even though you have no text selected if you hit Ctrl-C right now iTunes will copy the UDID onto the clipboard. You can't select the text in any way (since a click will change the display back to Serial Number) but trust me, this should work.

  6. Paste the UDID from the clipboard into an email and send it to your developer friend. He or she will thank you!

MKMapView is a Naughty Minx

OK, that was nasty to find. I've been plagued on and off by a crash bug that I only seem to see on the iPad and it's never been very reproducible. Today I was putting textures in the background of the iPad screens and found a reproducible crash. Hooray! Except as soon as I put a breakpoint in the crash would go away so there's some sort of race condition/multithreading going on. Mumble grumble.

The breakpoint was everyone's friend EXC_BAD_ACCESS. Of course this means the bad code wasn't anywhere near the actual crash. (And as an aside, surprising to me because I use ARC and therefore I don't write the retain and release code. So there's probably an ARC bug in here as well. Later I'll try to make a test app and submit a Radar.)

How did I find it? That in and of itself is a convoluted story and maybe worth relaying. I turned on NSZombieEnabled (in Xcode 4 you go to the Edit Scheme window and there's a checkbox in the Run/Diagnostics panel for Enable Zombie Objects) and discovered it was my TripMapViewController class receiving a respondsToSelector: message after it had been deallocated (and after the view wasn't onscreen anymore). This is a bit of a red herring because I use respondsToSelector: a fair amount so I scrubbed through all of my code and verified that I wasn't the culprit.

OK, I have to admit that stumped me for a moment. So it would appear that some other system thread is calling respondsToSelector with a pointer that it snuck past ARC. I did something hacky just to confirm the situation: I stashed a copy of the TripMapViewController in a static pointer, which should mean ARC no longer released the object. That worked and the crash stopped. Now what? After that I realized my object was still around and that I could overload respondsToSelector: and at least see the damn callstack. Turns out this controller gets a lot of respondsToSelector: messages; enough that you can't just stick a breakpoint in there. I did some more clunky things so that I could turn on a breakpoint after viewWillDisappear had been called. Sure enough, this big pile o' hacks worked for me: I could see the callstack of a bogus call. Problem is that it was all system stuff, with several calls just labeled "MKLongHash". If you Google MKLongHash you only get one hit which turns out to be a Stack Overflow thread about ARC and messages to zombie MKMapViews. Oh really?


Sure enough that's it. If you set the delegate of a MKMapView to a controller it is possible that ARC will incorrectly release the controller while some MKMap thing is still messing about. The solution provided in the article is to explicitly set and clear the delegate on viewWillAppear/viewWillDisappear. This worked for me. Maybe the next person who Googles for MKLongHash will find this helpful :-)

Legally Getting and Running X-Com UFO Defense on OS X

I've been reading a bit about the upcoming Firaxis XCom update and I've been getting a hankering to play the original X-Com. Well, I played it on the Playstation 1, I don't know if I have the disc anymore and even if I do, that's going to be annoying. I had a mouse for the original PS1, but who knows where that is, and who knows if I can even connect it to my PS3. I don't think I've got anything to connect a PS1/PS2 controller to my the PS3. (I know I did have a gizmo for moving Memory Cards over but I don't recall if it had a controller port.) And even if I got a mouse to work somehow … I don't want to play it in my living room with a mouse on the coffee table.

Anyway, a big hat tip here to my friend Tony who had mentioned to me at some point in the past that if you buy X-Com on Steam that it just ships inside an open source project called DOSBox. And you can download a version of DOSBox for OS X. So this morning while I was watching the Apple liveblogs I did all this. It works, but there are a few tweaks I had to make to make things convenient. Here's what you do.

  1. Buy X-Com on Steam. You can get the first game for $5 or a whole bunch of them for $15. I don't know if you can actually do this from the Mac Steam client, I did it in a Windows 7 virtual machine.
  2. Install DOSBox. Download it, and then put DOSBox.app in your Applications folder.
  3. Copy the files from Windows to somewhere useful on your Mac. I made a DOSBox folder in my Documents, but wherever works for you. Assuming your Steam is working in the default place you want to copy the folder C:\Program Files\Steam\Steamapps\common\XCom UFO Defense.
  4. When you get into DOS that long file name is going to be a pain. I renamed the folder to just XCom – so I have ~/Documents/DOSBox/XCom.
  5. At this point you could just run DOSBox manually, mount the folder, and run the stuff, but there's a better way and that involves a dosbox.conf file. The folder already contains one but you need to pass that to dosbox, and that's a pain as well. Here's the whole command that I use:
    /Applications/DOSBox.app/contents/macos/dosbox -conf /Users/tsanders/Documents/DOSBox/XCom/dosbox.conf
  6. This file didn't completely work for me. There was something not right about fullscreen mode but I didn't want the app in fullscreen on my 27" monitor anyway. The conf file also defaults to a 2x interpolation and I wanted to use the 3x. Lastly the volume was way too loud for me. So here's a list of changes I made:
    • Comment out fullscreen=true (so #fullscreen=true)
    • Change scaler=advinterp2x to scaler=advinterp3x
    • At the bottom in the [autoexec] section change the mount command to the proper path. Mine is mount c /Users/tsanders/Documents/DOSBox/XCom -freesize 1024
    • Add the line "mixer master 25:25" to set the volume levels 25% of maximum
  7. OK, so far so good but that command line is a pain in the rear to enter. That's easy to fix! Run Automator, select the Application type, then in Utilities pick a "Run Shell Script" action. Paste the command over the line that says "cat". You probably don't want Automator to wait for the command to complete, so be sure to add " &" at the end of the line.
    /Applications/DOSBox.app/contents/macos/dosbox -conf /Users/tsanders/Documents/DOSBox/XCom/dosbox.conf &
  8. Save the resulting Automator action in your Applications folder and you're done!
  9. Optional bonus step: Go to images.google.com and get a nice icon image - I just looked for "x-com ufo defense box". Find the app you made in the last step, select it in the Finder and hit cmd-I. In the info window that comes up you can select the icon (it should be the little Automator robot) and just paste an image from the clipboard.

At this point you have an icon in Finder you can double-click, or something you can launch from Spotlight. No more opening Terminal, navigating to the proper directory, or remembering the syntax of the DOSBox commands. Pretty cool.

In theory this ought to work for a large number of DOS games. Of course, the devil is really in figuring out the proper settings for that DOSBox config file. That's where the cool part is that the Steam file is already mostly correctly configured. (I didn't chase the fullscreen problem but I suspect it's related to having two monitors, it might work fine with a single monitor.)

Edited to add March 7, 2012 10:21 PM:When I was working on this I had Automator open and I didn't notice this but the first version of the Automator app continued to run until I quit the game, resulting in a turning gear icon in the menubar. The fix is simple: just put the command line into the background with a simple & at the end. I adjusted step 7 to reflect this.

Oh no you didn't VoiceOver

OK, let's say you're making an iOS app. And it's new so you go to use storyboards because they are awesome and you can target iOS 5.x. Swell. And you're going to use UITableViews and storyboards have that hot new prototype thing where you can lay out your cell right there in the UITableView and you're guaranteed you'll always get a cell from dequeueReusableCellWithIdentifier. Awesome! Well not so fast partner. Go read this Radar and this Radar. Yeah, that sucks. Short version is that works fantastically unless your user has turned on VoiceOver, at which point you don't get a cell at all. The stub code Xcode generates at that point will create a generic UITableViewCell with none of your custom layout. If you're lucky you'll get a blank cell. If you're unlucky your code assumed it got a custom cell type and crashes on some property access or method call. So what do you need to do? You have to old school it and just ignore the new layout feature. You can't require your users to turn off VoiceOver, that's not reasonable. You can leave the prototypes in and they will work in the VoiceOver off case but as far as I can tell there is no way to load a prototype cell from a storyboard. I suspect that you might just be able to rummage around in the nib and find a prototype but I don't see a proper way to do that. In the VoiceOver case you have to provide code that will load a cell from a nib file. You can leave the prototype cells in and that will work in the non-VoiceOver case but now you've got two cell prototypes and that's a bad idea. I do recommend leaving the call to dequeueReusableCellWithIdentifier in place though. Even with VoiceOver on the table can recycle old cells so if you do all of the cell identifier stuff then after a while your view can get a working set of cells that it just reuses on a scroll. Here's a code snippet that rolls this all up. It's not revolutionary but it gets the job done.
TripTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
// That call is supposed to always work, but it doesn't if the user has VoiceOver on. If they do, we'll engage le hack below
if (cell == nil) {
[[NSBundle mainBundle] loadNibNamed:@"TripTableViewCell" owner:self options:nil];
// The above will load our blankCell field with a new TripTableViewCell.
cell = blankCell;

With this code you make a nib that contains your custom cell. Then in the view controller you make an IBOutlet like so:
@property (nonatomic, retain) IBOutlet TripTableViewCell* blankCell;
In the nib you set the File's Owner to the controller and connect blankCell to the cell. Like I said, nothing shocking here just some old-school-ness in the new storyboard world …

iOS Beta Testers Wanted!

I'm putting the last few VoiceOver accessibility labels in my iOS app (RoadTrip) and then it's basically done. I want to take a stab at putting some custom textures in and I'm sure I'll find some new bugs once I turn off VoiceOver and go back to the iPad version but the end of the project is visible from here. If I know you in real life, you have a iOS 5.0 device available, and you're willing to do some beta testing for me I'd appreciate it. Get in touch with me! I'm hoping to release a beta version by the weekend.