Another Year, another Symbolication Problem
For me, this is an annual event it seems: struggling to get XCode to symbolicate stuff so it’s actually useful. The task: get symbols in my Instruments so I can see which bloody method is taking 10 seconds to execute.
The problem always seems to be Spotlight, which is used to locate the builds.
To cut a long story short: XCode places the dSYM files for the *current* build in ~/Library/Developer/Xcode/DerivedData and the dSYM’s for your archived builds in ~/Library/Developer/Xcode/Archives/ (if you’re using finder you’ll have to use ‘show package contents’ on the builds to see what’s inside).
Aside: is your Library directory hidden in Lion: chflags nohidden ~/Library/ to unhide.
Now the last time I was trying to symbolicate it was crash dumps, and some advice on SO advised me to add the DerivedData folder to my Spotlight exclusions so the symbolicator doesn’t get confused (I believe it worked at the time), of course this messes with symbolication Instruments, so be sure to remove it.
I love it when you can avoid Spotlight altogether, which just seems so flakey for things like this – and there is a good way (alt). I’ll summarise it here:
- With Instruments stopped, click on File -> Re-Symbolicate Document
- Search for your app name
- Click “Locate” and choose your dSYM from
~/Library/Developer/DerivedData/APP_NAME-XXXXXXX/Build/Products/[BUILD_TYPE]-[DEVICE-TYPE]/ - Click the Start button to begin profiling
With step 4, it’s possible you may have multiple folders with the same app name. The easiest way to find the one you need is to order by modification date, and pick the most recent.
For me, this fixed up Instruments on a per-execution basis, without needing to trick Spotlight into action. I expect once Spotlight has a chance to sort itself out, it may just work but you won’t find me holding my breath.
Hashbangs vs pushState
When Twitter jumped on the hashbang bandwagon, it prompted me to consider it too. I even did up a quick prototype on Geospike to see it working. Something made me uneasy though, so I put in on ice.
I’m happy I did, as these are some very convincing arguments against hashbangs, and for pushState. Using pushState alone means you can’t support IE, but as the author states “are page refreshes that bad?” – it is possible to make page loads fast, and this is a good example of something degrading gracefully.
Interesting summary of the conversation, and more pushState info.
stdin, stdout, stderr with proc_open in PHP
Want to use PHP as part of your toolchain? It’s a bit painful. If you want to pipe in some data from memory, and read it back into memory (why not! using tmp files is for wimps).
here’s the solution, thanks to richard at 2006 dot atterer dot net
// $command is the command to run, $stdin is your input. You get back $stdout and $stderr and $returnValue
// you'll probably want to wrap this in a function ;)
$descriptorSpec = array(0 => array("pipe", "r"),
1 => array('pipe', 'w'),
2 => array('pipe', 'w'));
$process = proc_open($command, $descriptorSpec, $pipes);
$txOff = 0; $txLen = strlen($stdin);
$stdout = ''; $stdoutDone = FALSE;
$stderr = ''; $stderrDone = FALSE;
stream_set_blocking($pipes[0], 0); // Make stdin/stdout/stderr non-blocking
stream_set_blocking($pipes[1], 0);
stream_set_blocking($pipes[2], 0);
if ($txLen == 0) fclose($pipes[0]);
while (TRUE) {
$rx = array(); // The program's stdout/stderr
if (!$stdoutDone) $rx[] = $pipes[1];
if (!$stderrDone) $rx[] = $pipes[2];
$tx = array(); // The program's stdin
if ($txOff < $txLen) $tx[] = $pipes[0];
$ex = NULL;
stream_select($rx, $tx, $ex, NULL, NULL); // Block til r/w possible
if (!empty($tx)) {
$txRet = fwrite($pipes[0], substr($stdin, $txOff, 8192));
if ($txRet !== FALSE) $txOff += $txRet;
if ($txOff >= $txLen) fclose($pipes[0]);
}
foreach ($rx as $r) {
if ($r == $pipes[1]) {
$stdout .= fread($pipes[1], 8192);
if (feof($pipes[1])) { fclose($pipes[1]); $stdoutDone = TRUE; }
} else if ($r == $pipes[2]) {
$stderr .= fread($pipes[2], 8192);
if (feof($pipes[2])) { fclose($pipes[2]); $stderrDone = TRUE; }
}
}
if (!is_resource($process)) break;
if ($txOff >= $txLen && $stdoutDone && $stderrDone) break;
}
$returnValue = proc_close($process);
I previously had an implementation using `fwrite` and `stream_get_contents` as some other people, and the docs suggested, which works fine for small inputs, but once you get something bigger than ~200k input, it can completely deadlock.
This implementation is better as it reads and writes the data when needed, keeping everything flowing and alive.
[[UIDevice currentDevice] uniqueIdentifier] Substitute
Identifying devices uniquely is handy. Apple deprecated their uniqueIdentifier property, with the severe warning “Do not use the uniqueIdentifier property”, so it’s time to migrate before they remove it altogether or start rejecting apps *sigh*.
With that in mind, I created a replacement method for UIDevice: UDID. It uses the device’s MAC address to generate a unique ID that is the same length as the old UDIDs. I was inspired by some other people’s solutions, but rolled my own implementation which I feel is neater, and more compatible (as it generates similar 40char UDIDs). You can fork it on github.
It’s not a drop-in replacement, for fear of monkey patching over an existing method. Just do a find & replace with: [[UIDevice currentDevice] UDID].
Of course: consider if device identifiers are right for you. To identify a specific install of your app (which can be migrated from one iPhone another due to loss/upgrading), generating a UUID and saving that as a NSUserDefault would work best (since it will transfer with the app data).
License: public domain.
Turbocharging git on Mac OS X
This weekend I discovered two awesome graphical tools to improve my git experience on Mac OS X:
The most awesome is KDiff3 (search for ‘Apple Mac OSX binary’ on that page for the Mac binary). This is a three-way merge tool with an editing panel below. Seriously where has this been all my life? Amazing.
Download it, and install – make sure it’s in your system PATH. Then simply run git config --global merge.tool kdiff3 to set it as your default merge tool. Now every time you get a conflict, your git mergetool command will actually be rather helpful! Basically you are shown the base revision (that both branches split from) in the middle, one branch either side, and an editor below allowing you to pick which side you want and/or edit the file directly.
The second tool I (re)discovered was SourceTree (Mac App Store DL Link). It is a Mac GUI client for git. I’m pretty comfortable with the command line, but what I love about this tool is it allows me to review my changes before I commit them (either staged or unstaged), discard hunks I don’t want, and of course open the file in question for editing. Very convenient. git diff is nice and all, but I love having that handy ‘discard hunk’ button in SourceTree so I can skip my silly changes. For me this is the most useful feature, though no doubt there are others. Oh and it’s free (it’s a bit confusing, as there is a “trial” period, but after the trial you simply register for free, and are given a license).
Migrating data in a Rails migration
Turns out it’s easy to whack any old piece of code into the migration for migrating your data, for example these work well for some arbitrary SQL statements (I used UPDATE ones…)
ActiveRecord::Base.connection.select_one('SELECT COUNT(*) FROM mytable')
ActiveRecord::Base.connection.execute('SELECT * FROM mytable')
Thanks revgeorge.
AppleIDs and multiple iOS developer accounts
“In the iOS Development Ecosystem the people are represented by two separate, yet equally important groups. The iOS Developer Users who create apps and the iTunesConnect Users who upload the apps. These are their stories.”
An iOS team is actually in two parts: the iOS Developer Team, accessed via the Member Center, and a completely separate iTunes Connect team.
It turns out that the one AppleID can belong to multiple iOS developer teams, and Apple asks you when you login to the member center which team you want to use. However iTunes Connect has no such feature, and each AppleID can only belong to one iTunes Connect “team”.
So you can re-use AppleIDs for developer accounts, but not itunes connect accounts. It’s up to you I guess if you want a totally separate AppleID for each team, or just each iTunes connect account.
monit
Monit for linux is a great way to make sure Apache is running.
I set it up with the help of this fantastic tutorial. My steps after the break.
NSDateFormatter format specifiers
Ever wanted the list of format specifiers?
Anything in single quotes is put through as-is.
Android Market Resources
Confused about what each of the images do and how they’re cropped?
Look no further than this awesome test app! Market link here.
Some high quality phone image marketing resources. I like this one.
