Overview of iOS Crash Reporting Tools: Part 2/2

In this second part of a series on iOS Crash Reporting Tools, you’ll learn how to get started with 5 of the most popular services: Crashlytics, Crittercism, Bugsense, TestFlight and HockeyApp. By Cesare Rocchi.

Leave a rating/review
Save for later
Share
You are currently viewing page 2 of 6 of this article. Click here to view the first page.

Crashlytics — Configuring the Project

Once you have logged into Crashlytics, you will be prompted to download a Mac OSX application that will help you to set up your first project.

To save you time, here’s the direct link to the Mac application. When running, the application appears in the menu bar on the top right as shown below:

Crashlytics in the menu bar

Click on the icon and enter your credentials when prompted. If this is your first time using Crashlytics, you should see an empty list of applications and your account name at the bottom, as shown below:

Crashlytics after login

Click on the New App button on the right. This will show you the list of recent projects opened in Xcode, like so:

Recent Projects in Crashlytics

If your app is not listed, you’ll need to perform the following steps:

  1. Click the “Other” button at the bottom to open a Finder window.
  2. Select the .xcodeproj file and click “Open”.
  3. Select your project from the list in Crashlytics and hit “Next”.

This will automatically open the project in Xcode and ask you to add a script to the Build Phase. From this point onward, the Crashlytics app will walk you through each step of installation process. Follow the instructions, and when you’re done, continue with the next step of the tutorial.

Crashlytics — Running the App

Now that you’ve completed the setup portion, you are now ready to try out Crashlytics. Run the application on your iOS device, swipe on a cell and tap Delete. The application will crash, as expected.

Restart the app and wait about a minute to make sure the crash report has propagated to the Crashlytics server. Then take a peek at the website to see if the crash report is live. You should also receive an email notification about a new crash in your application.

The new issue on the back-end should look like the following:

First issue on Crashlytics

At first glance, you will see the guilty line of code (SMViewController.m at line 80), the number of users affected, and the number of occurrences of this crash. Launch the app and make it crash again. You’ll now see the number of crashes of the same issue increase.

Click the row of that issue and you’ll see the extended report, as shown below:

Detailed view of the report on Crashlytics

Looking at the crash log, it’s clear that you need to counterbalance the deletion of a cell with the deletion of its corresponding element in the array populating the table view. To fix this bug, open SMViewController.m and modify tableView:commitEditingStyle:forRowAtIndexPath: to look like the following code:

- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
    if (editingStyle == UITableViewCellEditingStyleDelete) {
        [pizzaOrder removeObjectAtIndex:indexPath.row];
        [tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade];
    }
}

After you are done, build and run, push the app to your device, and test the application again. Once you have determined that you have fixed the issue, return to the Crashlytics crash report then set the issue status as closed, as shown below:

Crashlytics close bug

On to the second bug!

Crashlytics allows you to add log statements to your code to help track down bugs. Open SMViewController.m and add the following import statement at the top of the file:

#import <Crashlytics/Crashlytics.h>

Next, modify tableView:willDisplayCell:forRowAtIndexPath: in SMViewController.m as follows.

- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {
    if (indexPath.row == pizzaOrder.count-1) {
        CLS_LOG(@"posting notification");
        [Crashlytics setIntValue:pizzaOrder.count forKey:@"numberOfPizzas"];
        [[NSNotificationCenter defaultCenter] postNotificationName:LOAD_MORE_NOTIFICATION
                                                            object:nil];
    }
}

CLS_LOG is a macro provided by the Crashlytics framework that enables remote logging. In debug builds, it acts just like NSLog, passing strings to the console. For release builds, the log is sent along with the crash reports and optimized to be as fast as possible. In fact, Crashlytics’ own documentation boasts a 10x improvement over using regular NSLog() calls.

The method also uses custom logging which allows you to store information in key-value form. Think of this as a type of NSDictionary on the web server: you set the values of keys in the code, and you can read the values on the server when hunting down a bug.

In this case you are using setIntValue:forKey, but there are other methods available to store objects, floats and booleans as well. You can find more details about custom logging in the Crashlytics knowledgebase.

Run the application in Xcode and then stop it. Run it again on your device, scroll to the bottom, allow the app to crash, and restart the application after the crash.

The new issue will look like this on the Crashlytics dashboard:

Second issue on Crashlytics

It is clear that this is due to the lack of the method definition loadMore in SMWebEngine.m. If you were to add the definition for this method, and the crash would disappear. Although that’s not the point of this tutorial, so don’t worry about actually implementing it!

Notice that the detailed view of each issue provides information about the device like iOS version, and free space on disk and in memory. All these details might help you when you are hunting down the root cause of a crash.

Click on “More details…” in the middle of the page. This will show even more details like the type of device, orientation, plus the keys and log statements that you have spread throughout your code, as shown in the following screenshot:

Logs and keys on Crashlytics

This way you can have a path of breadcrumbs that can help to hunt down the cause of the crash. It is important to note that logs and keys are sent to the server as attachments to a crash log, so you won’t see them if there aren’t any crashes.

Crashlytics, unlike other services like TestFlight, is not a generic remote logging application, but rather a true crash reporting application. So even though your app may be full of logging statements, if the app never crashes, you’ll never see any of your logs!

One useful feature for beta testing is the ability to ask your users to provide some data to identify themselves. Crashlytics provides three ways to attach this data to a crash log:

[Crashlytics setUserIdentifier:@”123456”];
[Crashlytics setUserName:@”cesarerocchi”];
[Crashlytics setUserEmail:@”cesare@mailaddress.com”];

This way, you can identify who is experiencing a crash, and contact that tester to get more details.

Finally, you can configure some logging features on the back-end. Each application has a settings section that you can open by clicking the gear button, as shown below:

App settings on Crashlytics

From here you can disable reports from a specific version, or request a user for permission before sending data about the report. When you enable it (and you should!), you can customize the message as shown in the screenshot below:

Privacy on Crashlytics

Contributors

Over 300 content creators. Join our team.