Category Archives: Xcode

Visualizing Code Coverage with Xcode

After having a particularly good experience exploring and implementing unit tests in Visual Studio 2012 using the code coverage analysis found in the Premium SKU I decided it was time (past time!) to get a similar handle on testing my iOS applications.

Now I love Xcode but the tooling is, in my opinion, not as mature as Visual Studio in many respects: debugging experience, testing experience, analysis, and integration for 3rd-parties to name a few.

When it comes to unit testing and code coverage with Xcode, the story isn’t nearly as nice as that found in Visual Studio. For instance, your only option for running unit tests is to run all test cases at once. There is no test runner or dedicated UI and there is no way to run individual tests or easily toggle tests (other than individually toggling the membership of .m files in the test target). To put it simply, it’s a far cry from Visual Studio’s Test Explorer, much less something like CodeRush’s Test Runner. See the update at the bottom of the post for clarification on this.

When it comes to visualizing code coverage with Xcode – specifically iOS apps – there are several steps to take and a 3rd-party application is required.

The first step is to configure your iOS app target for code coverage. Select your app target in Xcode (not the unit test target) and, under Build Settings, enable the following settings for the Debug configuration:

  1. Generate Test Coverage Files
  2. Generate Profiling Code
  3. Instrument Program Flow

One Setting

Two Settings

Now, as long as your project is setup with a unit test target, you can click Product and then Test to run your unit tests.

This is where things start to get not-as-pretty-as-Visual-Studio. What this did was generate a bunch of files in a deeply nested location on the file system, namely:

~/Library/Developer/Xcode/DerivedData/[Project Name]-[Random Characters]/Build/Intermediates/[Target Name].build/[Configuration Name]-iphonesimulator/[Target Name].build/Objects-normal/i386

Yes. Really. For example, this is the path for a sample I created:

~/Library/Developer/Xcode/DerivedData/CodeCoverageSample-gtzzspgbzxcdhifewyfazdxkkwum/Build/Intermediates/CodeCoverageSample.build/Test-iphonesimulator/CodeCoverageSample.build/Objects-normal/i386

If you check the contents of this folder after taking the above steps, you should now see a collection of DIA, GCDA, GCNO, and related files.

The next step is to find a friendly way to view these results. There is nothing for this built into Xcode or provided by Apple. This is where a nice open source application called CoverStory comes in handy. This application loads the files generated by Xcode and displays an output similar to other code coverage tools.

You can download CoverStory here. After running the app, click the File menu, then Open, and navigate to the same ridiculous path mentioned previously (press ⌘⇧. to show hidden files & folders in Finder). This should display the breakdown of code coverage for your application.

CoverStory

Selecting .m files will show the individual lines of code covered by the unit tests.

Finally, depending on the linker flags your project uses there may be additional steps required to generate GCDA files with iOS 6. I’ve covered steps for working around that issue in a separate blog post here.

My next step will be to look into GHUnit, an alternative to the unit testing bundled into the Xcode IDE (OCUnit). While not integrated into Xcode, GHUnit does offer several improvements such as the ability to run individual tests or failed tests.

UPDATE: Martin Pilkington was kind enough to call to my attention that there is another way to enable and disable tests and test cases using Xcode schemes. Click on Product, then Scheme, then Edit Scheme (or press ⌘<). On the left of the scheme sheet select the Test action. On the right, in the list under Tests, you can expand the individual test targets, test cases, and tests, and enable and disable them via the checkbox in the last column.

Scheme Test Action Tests

You can also multi-select multiple tests and test cases and right-click to disable or enable a group.

Disable Tests

Thanks Martin! And while this is absolutely better than toggling the target membership of the .m test case files, I’d still like the ability to easily run a single test or test case. Right now, to target coverage of a single test or test case, I have to disable hundreds (on a larger project) of tests, then work on my one test, only to re-enable hundreds of tests afterwards.

What I’d personally like is the sort of simple features found in other unit test runners: easily select and run a single test, a single test case, failing tests, or all tests (without having to manually and individually select which tests to run).

UPDATE: Xcode 5 has since been released by Apple and now includes a full-blown Test Navigator for running unit tests.

Fix for Missing Code Coverage Files with Xcode

One of the things I’ve been working with lately is code coverage analysis using Xcode and CoverStory.

CoverStory Demo

While the experience is not as polished and complete as Visual Studio 2012, I’ve gotten most things working well enough.

One of the bigger hurdles I ran into was missing code coverage files when using iOS 6 to run unit tests. If I used iOS 5 or 5.1, the code coverage files were generated just fine. However, if I used iOS 6.0 or 6.1 the GCDA files specifically were not created.

I moved past this for a while but, as my code coverage increased, it became more important for me to test the iOS 6 specific code paths. I tried the Apple developer forums but had no luck, so I continued digging myself.

The first thing I noticed was that a brand new project created with Xcode did create GCDA files for iOS 6 and 6.1. This was promising as it meant that the problem was somewhere in my project.

After spending some time comparing project.pbxproj files (thanks to Marc Hoffman for pointing me in that direction), I was finally able to narrow the problem down to its cause. If you have an old enough iOS project, there’s a decent chance you’ll have one of the following flags specified in your Build Settings for Other Linker Flags:

  • -weak_library /usr/lib/libSystem.B.dylib
  • -weak-lSystem

Bad Setting

Among other things these flags allow apps that use features such as blocks and backgrounding to build for iOS 3. As it turns out, this setting also causes GCDA files not to be created when generating code coverage under iOS 6.

There are two options here:

  1. If the flag is not needed anymore you can remove it
  2. If the flag is necessary, you can create a new configuration for unit testing (this is also useful for setting up preprocessor macros)

In Xcode, select your project and select the Info tab. Click the plus button under Configurations and create a new configuration based on Debug.

Add Config
Dupe Debug

Name the new configuration Test.

Name Test

On the Build Settings tab, locate Other Linker Flags. Expand the setting so that each configuration is shown underneath it. For the Test configuration, remove the offending flag.

Clear Flag for Test

Now that the Test configuration is setup not to use the offending flag, you need to tell Xcode to use this configuration when testing. You can do this using schemes. Click on Product, then Scheme, then Edit Scheme (or alternatively press ⌘<). On the left of the scheme sheet select the Test action.

Scheme Test Action

On the Info tab, change Build Configuration from Debug to Test.

Select Test Config

With these settings in place the proper code coverage files should now be generated when running unit tests with iOS 6. Note that the path to the code coverage files will change, as the path is based on the configuration name which is now Test.

CoverStory

This took a while to figure out and hopefully Apple will fix the issue (I’ve submitted a bug report). In the meantime hopefully this post helps others who run into this issue!

Hip Shot Version 1.5 Available

Version 1.5 of Hip Shot is now available for download on the Apple App Store. This update to Hip Shot introduces the following improvements:

  • Added the ability to disable individual positions within each location
  • Added support for displaying information in Spanish and German

The #1 request from users since the release of Hip Shot has been the ability to disable individual positions in the application, for example subregions of the left thigh:
Disable Position

With this update it is now possible to customize these individual disabled positions in the Settings tab.

This update also brings localized translations for both Spanish and German. Now, if you have your language in iOS set to either of these languages the text in Hip Shot will be shown in your native language.

If you are able to help translate the phrases in Hip Shot, visit hipshotapp.com and click the link at the bottom of the page.

Objective-C Literals with Data Abstract

Xcode 4.4 introduced Objective-C Literals which I think are great. Objective-C Literals are a collection of language enhancements that make it possible to do many common practices and patterns in Objective-C by writing less code. This includes boxing numbers, working with arrays and working with dictionaries. For instance, here’s some sample code for writing and reading an array without using Objective-C Literals:

[array setObject:@"one" atIndexedSubscript:0];
[array setObject:@"two" atIndexedSubscript:1];
[array setObject:@"three" atIndexedSubscript:2];

NSLog(@"%@", [array objectAtIndex:0]);
NSLog(@"%@", [array objectAtIndex:1]);
NSLog(@"%@", [array objectAtIndex:2]);

Here is the same code, now using the new enhancements for working with arrays:

array[0] = @"one";
array[1] = @"two";
array[2] = @"three";

NSLog(@"%@", array[0]);
NSLog(@"%@", array[1]);
NSLog(@"%@", array[2]);

Xcode even includes a refactoring called Convert to Modern Objective-C Syntax that will help you convert most of your code to this newer format.

Data Abstract, a multi-platform library for data access by RemObjects Software, also supports this new syntax when dealing with rows of data. The syntax was added to Data Abstract, according to Marc Hoffman, right after the Objective-C Literals support was announced at WWDC. Here is an example of working with a row of data before this change:

[row setValue:@"one" forKey:@"firstColumn"];
[row setValue:@"two" forKey:@"secondColumn"];
[row setValue:@"three" forKey:@"thirdColumn"];

NSLog(@"%@", [row valueForKey:@"firstColumn"]);
NSLog(@"%@", [row valueForKey:@"secondColumn"]);
NSLog(@"%@", [row valueForKey:@"thirdColumn"]);

And here is the newer syntax:

row[@"firstColumn"] = @"one";
row[@"secondColumn"] = @"two";
row[@"thirdColumn"] = @"three";

NSLog(@"%@", row[@"firstColumn"]);
NSLog(@"%@", row[@"secondColumn"]);
NSLog(@"%@", row[@"thirdColumn"]);

Fantastic I think! Easier to write, easy to read, and a very consistent and familiar way to access data by subscript. However, there is no built in refactoring in Xcode to change your old DADataTableRow code to this new format.

Stuck doing this by hand? I think not!

You can migrate your code to the newer syntax using Xcode’s Find & Replace. The Find & Replace in Xcode supports two powerful features we’ll use here: Regular Expresion (Regex) patterns and being able to preview and reject changes one-by-one.

To get started, load up your project in Xcode. On the left, select the Search Navigator (or press ⌘3). At the top of the Navigator, select Replace if Find is selected. Click the magnifying glass with the down arrow to the left of the search box and click Show Find Options. Under Style, select Regular Expression.


To replace the instances of code where values are being written, use the following search pattern:

[(.*) setValue:(.*) forKey:(.*)];

And use the following replace pattern:

1[3] = 2;

To replace the instances of code where row values are being read, use the following search pattern:

[(.*) valueForKey:(.*)]

And the following replace pattern:

1[2]

Click the Preview button to preview changes first. You can use the sliders in the middle of the preview window to accept and reject individual changes.


Once you’ve reviewed the changes, click Replace and you’re done! I’m happy any time I can use Regular Expressions without ending up with more problems than I started with.

Help Localize Hip Shot


I’ve finished the work necessary to make Hip Shot available in any language that iOS supports. I’ve updated the homepage with a couple of links in the footer for those who can help translate a few words and phrases. As I receive translations I’ll update the footer to include those languages no longer needed.

Hip Shot is designed to help those who suffer from Multiple Sclerosis track their medical injections without having to resort to pen and paper. It is in use by folks world-wide and proceeds are donated to the National Multiple Sclerosis Society. If you have the time and ability, please take a few moments to translate these few words and phrases into a language you know and send them here.

SimpleDrawing 1.1 Available on the App Store


Version 1.1 of SimpleDrawing is available for free on the Apple App Store. This update brings a few bug fixes, along with a bucket tool and a brush tool. The brush tool has several patterns available.

SimpleDrawing is an open source drawing app for iOS. The latest source code for SimpleDrawing, including the changes found in version 1.1, is available on the public Git repo.

What’s New in Version 1.1
• Added a bucket tool
• Added a paint brush tool with multiple patterns
• Show individual drawing titles on the initial screen
• Show the name of the current drawing tool on the iPad
• Added new settings
• Improved alignment of controls on the iPhone 5
• Fixed bug: cannot redo text tool after undoing
• Fixed bug: photos traced have double transparency
• Fixed bug: app may allow landscape orientation on the iPad

SimpleDrawing Available Free on the App Store

A week ago I posted about SimpleDrawing, an open source drawing app for iOS that I created. The app is now available for free on the Apple App Store, which makes it super easy to try out before deciding to dig into the code.

This lowers the bar for trying out the finished product while also demonstrating that the techniques used and final product will pass the App Store submission process. And it’s also yet another fun, free drawing tool for the platform!

SimpleDrawing for iOS


Introduction

As the name implies, SimpleDrawing is a simple open source drawing app for iOS. I created SimpleDrawing to serve as an example of how to handle the basic drawing features on an iOS device, including:

  • Tools such as pen, line, text, rectangle, ellipse, and eraser
  • Individual tool settings such as primary and secondary color, line width, transparency, and font size
  • Importing photos from the photo album
  • Multi-level undo and redo operations
  • Layers with individual levels of transparency
  • Sharing via mail, Twitter, camera roll and more

The drawing functionality of SimpleDrawing can be used within your own applications with minimal effort. The design of the code also makes it easy to add your own tools by inheriting from SDDrawingTool and overriding (usually) only one method.

Installation

It is possible to use the drawing functionality of SimpleDrawing within your own project. First add the contents of the SimpleDrawing project directly to your Xcode project by drag-and-drop. Next, add the required frameworks: Quartz, Twitter, and MessageUI. Select the main.m file from SimpleDrawing and uncheck it’s “Target Membership” for your target in the File inspector. Finally, disable ARC using the -fno-objc-arc flag for the files BGRSLoupeLayer.m, BSBrightnessSlider.m, and RSColorPickerView.m.

Usage

Once the required files are included in your project, with just a few lines of code you can display a view that lets you browse and create new drawings:

//instantiate the view controller
NSBundle *bundle = [NSBundle bundleForClass:[SDDrawingsViewController class]];
UIStoryboard *storyboard;
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
    storyboard = [UIStoryboard storyboardWithName:@"SDSimpleDrawing_iPad" bundle:bundle];
} else {
    storyboard = [UIStoryboard storyboardWithName:@"SDSimpleDrawing_iPhone" bundle:bundle];
}
SDDrawingsViewController *viewController = [storyboard instantiateInitialViewController];

//present the view controller
[self presentViewController:viewController animated:YES completion:nil];

Using the SDSimpleDrawing_iPad storyboard presents the user with a suitable iPad UI:

You can download the source code for SimpleDrawing at my repository here.

UPDATE: The SimpleDrawing app is now available for free from the Apple App Store if you want a free and easy way to try the app.

FileSystemView for iOS Developers

Introduction

When developing an iOS application with persistent data, having an easy way to browse the file system from within the app can be very beneficial. It’s possible to view files in Xcode Organizer with your device tethered via USB, and it’s possible browse the OS X file system to view files created in the simulator. However, having a view that can be tailored to show your application-specific directories available directly within the app is far more convenient. That’s where FileSystemView comes in.

Installation

FileSystemView is easy to include in any iPhone, iPod or iPad project. Simply add the contents of the FileSystemView project directly to your Xcode project by drag-and-drop. Specifically you’ll need to include the contents of the Views, ViewControllers, and Categories directories.

Usage

Once the required files are included in your project, with just a few lines of code you can display a view that lets you navigate the file system at a custom root path, and with a custom starting path:

//instantiate the view controller
NSBundle *bundle = [NSBundle bundleForClass:[FSDirectoryViewController class]];
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"FSFileSystemView" bundle:bundle];
UINavigationController *navigationController = [storyboard instantiateInitialViewController];
FSDirectoryViewController *viewController = (FSDirectoryViewController*)navigationController.topViewController;

//set properties on the view controller
viewController.rootPath = [self drawingsDirectory];
viewController.rootPathTitle = @"All Drawings";
viewController.startingPath = [self photoDirectory];
viewController.navigationItem.title = @"Drawing Contents";

//present the view controller
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {

    [self.popoverController dismissPopoverAnimated:YES];
    self.popoverController = [[UIPopoverController alloc] initWithContentViewController:navigationController];
    [self.popoverController presentPopoverFromBarButtonItem:self.folderViewButton permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];

} else {

    [self presentViewController:navigationController animated:YES completion:nil];

}

The view shows file counts and file sizes, including recursive counts for directories. In addition the view lets you drill down into sub-directories, navigate to a customizable root path, and view individual file details.

You can grab the source code from my Bitbucket repo here.

UPDATE: The repository was incorrectly setup when I originally posted this. The repo was public but the wiki (which is the landing page) was private. That is resolved now and the repo should be publicly accessible.

Hip Shot Update Brings Improved Diabetes Support

Version 1.2 of Hip Shot is now available in the Apple App Store. This update incudes the following:

  • You can now track medicine, doses, and carbs with Hip Shot
  • You can build a medication list with default dosages, and also flag a medicine as default
  • Settings are now synchronized between devices using iCloud

With this update, Hip Shot’s feature set is expanding to make the app more useful to those who suffer from illnesses other from Multiple Sclerosis, such as Diabetes.


You can see a video showing some of these new features here.