Analyzing iOS crash dumps with Xcode

The best way to analyze a crash in an iOS app is if you can reproduce it directly in the iOS simulator in debug mode or on a local device connected to Xcode. Sometimes you have to analyze a crash that happened on a device that you do not have direct access to. Maybe the crash was discovered by a tester who is located in a remote place. In this case the tester must transfer the crash information to the developer and the developer has to import it in Xcode. The iOS and Xcode functionalities for this workflow are a bit hidden, so that the following step-by-step guide can help.

Finding the crash dumps

iOS stores crash dumps for every crash that occured. You can find them in the Settings app in the deeply nested menu hierarchy under Privacy -> Analytics -> Analytics Data.

There you can select the crash dump. If you tap on a crash dump you can see its contents in a JSON format. You can select this text and send it to the developer. Unfortunately there is no “Select all” option, you have to select it manually. It can be quite long because it contains the stack traces of all the threads of the app.

Importing the crash dump in Xcode

To import the crash dump in Xcode you must save it first in a file with the file name extension “.crash”. Then you open the Devices dialog in Xcode via the Window menu:

To import the crash dump you must have at least one device connected to your Mac, otherwise you will find that you can’t proceed to the next step. It can be any iOS device. Select the device to open the device information panel:

Here you find the “View Device Logs” button to open the following Device Logs dialog:

To import the crash dump into this dialog select the “All Logs” tab and drag & drop the “.crash” file into the panel on the left in the dialog.

Initially the stack traces in the crash dump only contain memory addresses as hexadecimal numbers. To resolve these addresses to human readable symbols of the code you have to “re-symbolicate” the log. This functionality is hidden in the context menu of the crash dump:

Now you’re good to go and you should finally be able to find the cause of the crash.

Advertisements

Clean Code OSX / Cocoa Development – Setting up CI and unit testing

Prerequisites: Xcode 4 and Java 1.6 installed

To start with the tool chain used by clean code development you need a continuous integration server.
Here we install Jenkins on OS X (Lion) for Cocoa development (including unit testing of course).

Installing Jenkins

Installing Jenkins is easy if you have homebrew installed:

brew update
brew install jenkins

and start it:

java -jar /usr/local/Cellar/jenkins/1.454/lib/jenkins.war

Open your browser and go to http://localhost:8080.

Installing the Xcode plugin

Click on Manage Jenkins -> Manage Plugins
and install the following plugins:

  • Git plugin
  • Xcode plugin (not the SICCI one)

Setup Job

On the Jenkins start page navigate to New Job -> Freestyle

Choose Git as your Version control system (or what is appropriate for you). If you want to run a local git build use a file URL, supposing your project is in a directory named MyProject inside your home directory the URL would look like:

file://localhost//Users/myuser/MyProject/

Add a Xcode build step under Build -> Add build step -> Xcode
and enter your main target (which is normally your project name)
Target: MyProject
Configuration: Debug

If you got Xcode 4.3 installed you may run into

error: can't exec '/Developer/usr/bin/xcodebuild' (No such file or directory)

First you need to install the Command Line Tools Xcode 4 via Downloads Preference Pane in Xcode (you need a developer account) and run

sudo xcode-select -switch /Applications/Xcode.app/Contents/Developer

Done!
Now you can build your project via Jenkins.

GHUnit Tests

Since we want to do clean code development we need unit tests. Nowadays you have two options: OCUnit or GHUnit. OCUnit is baked into Xcode right from the start and for using it in Jenkins you just create an additional build step with your unit testing target. So why use GHUnit (besides having a legacy project using it)? For me GHUnit has one significant advantage over OCUnit: you can run an individual test. And with some additions and tweaks you have support in Xcode, too.

So if you want to use GHUnit start with installing the Xcode Templates.
In Xcode you select your targets and create a new target via New Target -> Add Target -> GHUnit -> GHUnit OSX Test Bundle with OCMock
This creates a new directory. If you use automatic reference counting (ARC), replace GHUnitTestMain.m with the one from Tae

Copy RunTests.sh into UnitTests/Supported Files which copies the file into your UnitTests directory. Make it executable from the terminal with

chmod u+x RunTests.sh

In Xcode navigate to your unit test target and in Build Phases add the following under Run Script

$TARGETNAME/RunTests.sh

In Jenkins add a new Xcode build step to your job with Job -> Configure -> Add Build Step -> Xcode
Enter your unit test target into the Target field, set the configuration to Debug and add the follwing custom xcodebuild arguments:

GHUNIT_CLI=1 GHUNIT_AUTORUN=1 GHUNIT_AUTOEXIT=1 WRITE_JUNIT_XML=YES

At the time of this writing there exists a bug that the custom xcodebuild arguments are not persisted after the first run.

At the bottom of the page check Publish JUnit Test Report and enter

build/test-results/*.xml.

Ready to start!