Blog

Tag Archives: Scripts

Fixing Xcode 4’s symbolicate utility to get comprehensible crash logs

‘symbolicatecrash’ is the Developer Tools utility which replaces all those meaningless addresses from crash logs with actual symbol names and source code references. It lives at some obscure folder within /Developer – use find to dig it up and symlink it into /usr/local/bin if you wanna use it conveniently from the command line.

Anyway, after plenty of frustration, I noticed some chatter about the damn thing being busted in Xcode 4. Figures!

There’s an alternate third party version on GitHub, but this didn’t really help me – I still got inscrutable errors, so I took a look at the original.

The version that comes with Xcode 4 appears to have some problems distinguishing, say, an iPhone Simulator build of the app from a native build sitting in the Archives folder. I’d just see an error about otool and some binary living in the iPhone Simulator folder.

Digging into the errant symbolicatecrash source, I noticed that the code that finds the executable path tests each candidate using otool, but doesn’t seem to be able to comprehend the output from otool caused by running it on the wrong architecture.

So, replacing the rather unhelpful ‘die’ statement on line 323:

die "Can't understand the output from otool ($TEST_uuid -> '$otool -arch $arch -l $path')";

With a “No, it ain’t this executable” response:

return 0;

…solves the problem immediately. Now I can drag crash logs straight into the Organizer in Xcode, and it’ll symbolicate correctly.

Also tagged , , | Comments closed

Objective-C + Cocoa on the Command Line

Sometimes there’s just one tiny snippet of Cocoa code that you want to test — maybe to find out the output of NSDateFormatter for various cases, testing out some text replacement routine, or testing out some image drawing code.

It’s often too much trouble to create a new XCode project and set up the framework to do one simple test, which is why I put together this little shell script that lets you run Cocoa code from the command line:

$ runcocoa 'NSDateFormatter *formatter = [[[NSDateFormatter alloc] init] autorelease]; [formatter setDateFormat:@"d MMM, h:mm a"]; NSLog(@"%@", [formatter stringFromDate:[NSDate date]]);'

2011-02-23 20:02:10.313 runcocoa-output[28025:903] 23 Feb, 8:02 PM

You have full access to all Cocoa libraries, and in iOS mode, access to most iOS stuff too, straight from the command line.

Update: This is now available as a GitHub project Read More »

Also tagged , | Comments closed

Resuming ADC downloads (‘cos Safari sucks)

So, Safari’s resume facility is just awful — it’ll randomly restart downloads from the beginning, clobbering anything that’s already been downloaded, and the resume button will frequently disappear entirely and mysteriously from the downloads window. And if the session has expired, it’ll cause all kinds of havoc.

Anyone downloading the gazillion-gb iOS/Mac SDK + XCode on a slow and/or expensive connection will know the sheer fisticuffs-inspiring irritation this creates — speaking personally, living on a mobile broadband connection that’s usually changed at £3 per gig and often runs about as fast as I could send the data via carrier pigeon, this usually makes me want to storm Cupertino with a pitchfork.

Okay, so I could probably use Firefox or something else, but instead I figured I’d whip up* a shell script that lets me use my favoured long-haul download tool – curl. And in case there were any other sufferers of insanely-priced broadband and Safari’s antisocial behaviour, I thought I’d share it.

It’ll ask for your Apple ID and password, and store it in the keychain for you, and it’ll resume from the current working directory.

Chuck it somewhere like /usr/local/bin, make sure it’s executable (chmod +x /usr/local/bin/adc_download.sh) and call it from Terminal like:

adc_download.sh https://developer.apple.com/devcenter/download.action?path=/Developer_Tools/xcode_4_gm_seed/xcode_4_gm_seed_.dmg

If you’ve already started the download in Safari, just grab the partially-downloaded file from within the .download package Safari creates.

Here ’tis:

ADC Download Script (on Github)

P.S. I’d be interested to see how incremental updates fare when transferred from an intermediate server with rsync. It’s rather bizarre that Apple reissue the whole 3.x gb SDK with each update, rather than offering a ‘patch’ (I guess Apple lives blithely in the world of cheap bandwidth!), and it makes me wonder whether there’d be sufficient correlation between versions to save some bandwidth by avoiding transferring the similarities…

* read: spend hours on, as is my way.

Also tagged , | Comments closed

OS X service to filter selected text through a shell command

The UNIX shell provides a host of extremely useful utilities for modifying text. This OS X Automator service makes all of them available for filtering text in all OS X applications.

This can be handy for performing quick operations, like replacing text with regular expressions, sorting lists or swapping fields around.

When triggered, the service requests a command to use for filtering, then runs the command and replaces the selected text with the result.

Some sample operations:

  • Sort lines alphabetically/numerically: sort or sort -n
  • Change to lowercase: tr "[:upper:]" "[:lower:]"
  • Replace a spelling mistake, taking care of case: sed -E 's/([tT])eh/\1he/g'
  • Re-order elements in a tab- or comma-separated list: awk '{print $2 $1}' or awk -F, '{print $2 "," $1}'

Filter through Shell Command service

Put it in Library/Services, and it should appear in the ‘Services’ menu.

Filter through Shell Command.zip

Also tagged , , | Comments closed

Browsing Core Data databases using F-Script

F-Script, the Cocoa-based scripting environment, now provides some great tools for exploring Core Data databases.

I couldn’t figure out how to easily open up my databases, other than manually creating a managed object model, then a persistent store coordinator, then a managed object context on the console. I couldn’t find any existing tools, and I wanted a quick workflow for opening up my databases, so I put together a script that prompts for the application bundle or .xcdatamodel(d) data model file, then prompts for the XML (.xml), binary (.binary) or SQLite (.sql or anything else) database file, and opens up the inspector.

I wrote it as an Applescript that just calls upon F-Script to evaluate the script, and saved it in an application bundle so I can pull it up quickly.

Here it is:

Core Data Browser.app

201004101417.jpg

It just needs the F-Script app to be available.

Upon opening, the managed object context is available on the console as “context“. So, aside from using F-Script’s object browser, you can also do things like:

> request := (NSFetchRequest alloc) init
> request setEntity:(NSEntityDescription entityForName:'MyEntity' inManagedObjectContext:context)
> request setPredicate:(NSPredicate predicateWithFormat:'type = 3')
> result := context executeFetchRequest:request error:nil
> result
_PFArray {<nsmanagedobject: 0x2006cf740> (entity: MyEntity; id: 0x20064c9e0 <x -coredata://BAC82A67-CC41-48C2-8A96-693B67A501D6/MyEntity/p1> ; data: <fault>), 
<nsmanagedobject: 0x2006bdc80> (entity: MyEntity; id: 0x20064c9c0 <x -coredata://BAC82A67-CC41-48C2-8A96-693B67A501D6/MyEntity/p2> ; data: <fault>), 
<nsmanagedobject: 0x2006bc680> (entity: MyEntity; id: 0x200651180 <x -coredata://BAC82A67-CC41-48C2-8A96-693B67A501D6/MyEntity/p3> ; data: <fault>)
...
</fault></x></nsmanagedobject:></fault></x></nsmanagedobject:></fault></x></nsmanagedobject:>

Update: Now has better error reporting, and the option to load classes from a bundle.

For those interested, here’s the original F-Script: Read More »

Also tagged , , , | Comments closed

Searching through Subversion history

Occasionally I need to search back through old versions of projects to find a piece of code I want to resurrect or just use as reference — I haven’t found any easy built-in way to do this, so I adapted this useful script to allow me to grep through all history from within a Subversion working directory, like:

$ svngrep SecItemCopyMatching *
LSAddAccountController.m @r7: SecItemCopyMatching((CFDictionaryRef)[NSDictionary dictionaryWithObjectsAndKeys:
LSAddAccountController.m @r4: SecItemCopyMatching((CFDictionaryRef)[NSDictionary dictionaryWithObjectsAndKeys:
LSAddAccountController.m @r2: SecItemCopyMatching((CFDictionaryRef)[NSDictionary dictionaryWithObjectsAndKeys:
LSAddAccountController.m @r1: SecItemCopyMatching((CFDictionaryRef)[NSDictionary dictionaryWithObjectsAndKeys:

Here’s the script:

#!/bin/sh
pattern=$1
shift
 
for file in $@; 
do
  svn log -q "$file" 2>/dev/null | perl -ne 'print "$1\n" if /^r(\d+)/' | 
  while read r 
  do
    match=`svn cat -r $r "$file" | grep "$pattern"`
    result=$?
    if [ $result -eq 0 ]
    then
      /bin/echo -n "$file @r$r: "
      /bin/echo $match;
    elif [ $result -ne 1 ]
    then
      exit 2
    fi
  done
done;
Also tagged | Comments closed

Using custom DNS servers from the iPhone and over Internet Tethering

For those of us the roam around on network connections, OpenDNS and Google Public DNS provide public DNS servers which offer better security than using arbitrary DNS that’s assigned to us when we connect to a network. This means that rather than trusting the assigned DNS server — which could be a malicious third party that’s attempting a man-in-the-middle attack — we always use a trusted server.

In OS X, normally, one can specify custom DNS servers in Network Preferences, but when using Internet Tethering with the iPhone, no options are available.

It’s possible to set DNS configuration on the command line, though, as mentioned in this MacOSXHints article.

This technique can be used within a shell script to make things easier.

As it happens, if you have a jailbroken iPhone, the trick works there too — just ssh in as root, copy the script over, and run it from the iPhone.

The one caveat is that the DHCP client both on the iPhone and on Mac OS X will routinely reset the servers — I haven’t found a way to combat this yet, other than routinely re-running the script.

We have been using mobile broadband from my iPhone while we’ve been travelling; our current provider seems to go offline almost every evening — a quirk which I’ve just discovered is related to their faulty DNS server.

Using Google’s public DNS servers instead fixes this problem, so I was after a way to configure both the iPhone and OS X to use the servers.

Also tagged , | Comments closed

Textmate: ‘git diff’ in FileMerge

I found myself wanting to pick through some changes I made under a git repository recently, discarding some and adapting others. The FileMerge utility that comes with the Mac OS X Developer Tools is great for this purpose, but in TextMate, there’s currently no way to compare uncommitted changes in a git repository using FileMerge.

Now there is!

View Uncommitted Changes in FileMerge.tmCommand.zip

Double click to install it in Textmate; it appears under the ‘Git’ bundle. I suggest you then select the ‘Git’ bundle group header, and drag this command (‘View Uncommitted Changes in FileMerge‘) up to the top of the menu list on the right, so it’s accessible via Control-Shift-G, 1.

It’s based on filemerge.tmbundle.

Also tagged | Comments closed