Faux Pas

Resource File Reference Errors in Xcode Projects

Ali Rantakari
March 12, 2015

In iOS and Mac apps, resource files (e.g. images) are included into the app bundle and loaded in code by using strings referencing their filenames:

[NSData dataWithContentsOfFile:
 [[NSBundle mainBundle] pathForResource:@"Foo" ofType:@"bar"]];

In most cases, developers quickly notice when their filename references are incorrect. However, there are some conditions that might prevent this discovery even during initial development, as well as some situations where these references might become incorrect long after initial development.

Let’s look at some examples.

Renamed files

Once, after submitting an update to an iOS app to the App Store, I downloaded the updated app on my iPhone and immediately noticed how a prominent image was completely missing from the initial view in the app. This took me completely by surprise — I had manually tested the app quite well before the release, both on the simulator and on an actual device.

Turned out, the problem was that I had simply renamed the file, but failed to update the line of code that loads it from disk into a UIImage object:

self.imageView.image = [UIImage imageNamed:@"old_name.png"];

It seems like this should be trivial to catch — just run the app, and the image won’t show up, right?

Well, yes — assuming:

  • You exercise the relevant feature during testing
  • You clear the build in Xcode before running the app.

The file still exists, with its old name, in both the Xcode build directory, and in the current device/simulator installation. Xcode’s build and installation process simply copies files over, and doesn’t worry about removing old files that don’t exist in the project anymore. So unless you clear the build folder, the end result will be that the file will exist with both the new and the old names in the build that you’ll be testing.

Faux Pas would have caught this. It statically determines the resources that are actually installed for your Xcode project target, and warns you if your code or XIBs are referring to filenames that are not in that list. Even if you haven’t remembered to clear the build and to exercise the relevant feature.

Case sensitivity

iOS devices have a case-sensitive filesystem, while Macs (and therefore iOS simulators) have a case-insensitive filesystem.

This is an important distinction to make, especially if you primarily use the simulator during development: if your project has a resource file called Foo (note the capital F) and you load it in code using the string literal @"foo", the file will load correctly in the simulator but fail to load on an actual device.

Apple’s Technical Q&A QA1697 discusses this issue.

This is a relevant issue also for developers of Mac apps, but for a different reason: although Macs have a case-insensitive filesystem by default, end users can of course format their disks to be case-sensitive (and you don’t want that to break your app).

Faux Pas catches these kinds of mistakes as well, because it performs case-sensitive comparisons, just like the iOS filesystem.

The relevant rules

None of the standard development tools can help you notice these kinds of errors, but Faux Pas can.

These checks are implemented in the Code refers to unknown resource and XIB refers to unknown resource rules.