Using Custom File Types to import data into your iOS Apps

Disclaimer: This is a repost of my entry on the Chariot Solutions blog.

Introduction

I recently came across a situation where I needed the ability to share data between users of the same iOS application. Unfortunately, these users can not share an iCloud account and there is no server side components to this application. It is a standalone app.  Services like DropBox were not really an option either, as the devices are owned by an enterprise and will not have any service like that deployed onto them.

One solution is importing data via custom file types. Files can be sent to a device numerous ways (e.g. email, drop box, etc.), but for this post we will assume email. iOS makes it very simple to define a custom file type that your app can handle. This way, when the device receives an email with that type as an attachment, the user can select our app, giving it access to the underlying file. This post will walk through creating a simple app to access the contents of a text file received via email.

Create the Project

Lets start by creating a new project in XCode. I created a single view iPad application and called it “CustomUTIHandler”. I always use ARC. You can choose to use storyboards or not, as the UI in this app will do nothing more than display the contents of our file. The resulting project for this post can be found at:https://github.com/stevenpsmith/CustomFileHandler.

Define the File Type

The next thing is to define a file type extension that our application will support. This is also known as a Uniform Type Identifier (UTI). For our purpose, we will use a filetype of ‘csm’ (for Chariot Solutions Mobile). The contents of this file will be some string. It could really be almost anything, but for simplicity we will use a string. For a list of Apple defined UTIs, look here: http://developer.apple.com/library/ios/#documentation/Miscellaneous/Reference/UTIRef/Articles/System-DeclaredUniformTypeIdentifiers.html#//apple_ref/doc/uid/TP40009259-SW1.

Once we know what our custom file type extension is, we can add support for it to the project by modifying the Info.plist file for the project. We are going to be the owner/exporter of the new file type, so we add the “Exported Type UTIs” key to the Info.plist file. The default definition that gets created looks like this:



Based on the bundle key definitions found here: https://developer.apple.com/library/mac/#documentation/General/Reference/InfoPlistKeyReference/Articles/CocoaKeys.html, we can fill in the required values. Since our example only has one file type that it is defining and the underlying data is text, we can add the system defined identifier for text to the “Conforms to UITs” item:

public.text

Next we need to add the identifier for our custom UTI. Apple recommends using the reverse DNS format in order to ensure our new UTI is unique. I will be using the following:

com.chariotsolutions.customUTIHandler.csm

Finally, we want to identify the file extension that our app will be handling. This is defined under the “Equivalent Types” node. Add a node under the equivalent types with a name of “public.filename-extension” and a value of “csm”. You can optionally add a “Description” element under the Item for the exported type. My Info.plist now looks like this:

Support our new File Type

In order for our app to be recognized by the OS as supporting the newly defined file type, we need to add a “Document types” declaration to our Info.plist file. Doing so gives us the following in our Info.plist file:

The possible keys for the CFBundleDocumentTypes property can be found here: http://developer.apple.com/library/ios/#documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html#//apple_ref/doc/uid/TP40009249-101685-TPXREF107. We can add anything for the “Document Type Name” value. The handler rank will affect the order that Launch Services uses to present apps that handle this file type. Since our app is really the owner of this file type, we will use that as the handler rank. Now we need to add the “Document Content Type UITs” that our app will handle. In this case, we are only handling one type (as defined in the export key above):

com.chariotsolutions.customUTIHandler.csm

Just for fun, we will also give our file type an image icon (included in the project). The specs for the image are defined in the keys document referenced above (64×64 in this case). So our final Info.plist looks like the following:

Now all we have to do is create a text file with a “.csm” extension and email it to our device. Once there, long press the resulting icon and we should see our app listed as one of the “Open in” apps.

Once we select our app, it will launch and pass the file URL to this app delegate method:

- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation
So, adding a simple NSLog statement to the method and we can display the contents of our text file:
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation {
   if (url){
      NSString *str = [NSString stringWithContentsOfURL:url encoding:NSUTF8StringEncoding error:nil];
      NSLog(@"The file contained: %@",str);
   }
   return YES;
}

Important Safety Tip

The files that are being opened by the application are actually copied into a directory called “Inbox” within the apps Documents directory.  My file was called “This is a test.csm” (great name right, what am I a windows user?).  As shown in the image below, there are copies for each time I imported it on my device.

These files should be cleaned up as required by your app.

Summary

So by adding some configuration to our apps Info.plist file and implementing a delegate method, we can handle any uniform types within our app.  The source code for this project can be found at https://github.com/stevenpsmith/CustomFileHandler.  I added some code so that it will display the contents of the file on the screen….very exciting.

Added Bonus

Since we are declaring to launch services that our app handles “csm” files, drop your custom file type into drop box.  Assuming you have the drop box app on you device, find the document in the app and try to open it.  You should get “Unable to view file”.  But if you tap the icon in the upper right of the screen, you should get a list of apps that can open that file….including our app.

It’s like magic 🙂  You see those other apps listed because we defined our UTI as text type, and those apps will handle text documents.

Advertisements

9 comments

  1. Just desire to say your article is as amazing.
    The clarity in your post is simply excellent and i could assume you’re an expert on this subject. Fine with your permission allow me to grab your RSS feed to keep up to date with forthcoming post. Thanks a million and please carry on the rewarding work.

  2. Hello There. I found your blog using msn. This is an extremely well
    written article. I will be sure to bookmark it and return to read
    more of your useful information. Thanks for the post.
    I’ll definitely return.

      1. such a nice tutorial.
        But i want to know what all type of document file format supported in ios for displaying in pp. E.G. “.doc”,”.pdf”,”.ppt”..etc

      2. There is a link to the apple docs in the “Define the file type” section above. If you look at the docs, you’ll see the definitions for power point. Hope that helps.

  3. Hi Steven, very nice post and I hope you can help with my problem. I was able to register my app to open a custom extension file when attached to an email, but unfortunately if i use safari to open the same file posted as a link on my page it does not work. Shouldn’t the “Document Types” part be sufficient to make the “Open with ” dialog pop up? I even tried using a known filetype such as pdf, but still nothing. Thanks so much
    giangi

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s