Sebastien Pouliot December 17, 2012 ,

Most mobile application ship with read-only assets: images, sounds, videos, documents, databases. Assets, both in numbers and in size, tend to grow over time. Large assets that take many seconds or even minutes to transfer to the device can really slow down your development. Copying the same static assets each time you deploy your application is wasted time. Surely we can do better.

On iOS there’s a little-known solution to this situation. The trick is to:

1. Enable iTunes sharing on your application. That’s basically adding UIFileSharingEnabled to your application’s Info.plist file;

2. Use iTunes to copy your assets into your device(s);

3. Adjust your application to load the assets from the <Application_Home>/Documents directory;

This last step can be done by changing your paths from using NSBundle.MainBundle.BundlePath to Environment.GetFolderPath(Environment.SpecialFolder.Personal).

Adding those few changes can save you quite a bit of time. However they require modifications to your application and project files that might cause you other issues later. E.g.

  • Enabling iTunes sharing is useful for some applications, i.e. you might want to keep this option in your released applications. However it does not make sense for many applications so you’ll likely want to disable it for non-debug builds. Apple has been known to reject applications enabling this settings without a useful purpose;
  • You must remove the asset references from your project, or they will still be uploaded to the device. This will break your non-debug builds.

Here is a safer, step-by-step way to do this for Debug builds, while keeping your other build configurations unmodified.

1. Let’s create an empty MonoTouch application called LargeAssets. Replace the AppDelegate.cs source with this:

2. Add a large asset, e.g. a 80MB sqlite database, to your application and make sure its Build Action is set to Content.


3. Build and then deploy to your device. For reference note how much time is needed to deploy the application to your device.

For the 80MB test case deploying on an iPad 3 takes 19015 ms for a Debug build and 17910 ms on a Release build. The last being a bit faster since binaries are smaller (smaller AOT’ed executable, IL stripped assemblies) and no debugging symbols files are present.

Now that we have our baseline let’s optimize it – starting by the creation of two files for each existing asset. From a Terminal windows inside your project directory do the following:

Keep your LargeAssets.csproj unchanged, i.e. referencing LargeDatabase.sqlite. Note: If you keep your assets under source control then make sure you keep only one huge asset (and two empty versions).

Next we need to add a Custom Command to your project – for all Configurations (e.g. Debug, Release, Ad Hoc and AppStore). The Command to invoke, Before Build, is:


The shell script itself, below, can be added inside your project.

That will ensure the script is being called before starting a new build. In turn the script will do two actions for your project:

  1. It will use PlistBuddy to add the UIFileSharingEnabled value on Debug build. It will also remove this key from all other build configurations;
  2. It will copy either the *.Debug or *.Release assets to their original asset name (note: only in the main project directory, you’ll need to adapt the script if you have several directories or different requirements). This ensure that:
    • all assets will be empty for Debug builds, giving your faster device deployment times;
    • all assets will be just like before for non-Debug builds;
    • your .csproj files are kept unmodified.

Next you need to adjust your application to load the assets from the “right” location. For our example replace the earlier AppDelegate.cs source code with this one:

Finally try building/deploying the application again for both Debug and Release builds and compare the required time with the original version.

With our 80MB database we now get 4801 ms for a Debug build (only 25% of the original time) and 17567 ms for the Release build (98%) which not a surprise since it’s almost identical to the original code and .app size.

Exactly how much time you can save depends on your assets size and how often you update them, i.e. need to use iTunes to copy them.

Discuss this post on the Xamarin forums