UIDocumentInteractionControllerを使ったデータ共有

iOSアプリでUIDocumentInteractionControllerを使うと、他のアプリに画像ファイルやpdfファイルなどを送信することができます。 かなり古く(iOS3.2)から使える便利な機能なんですが、なぜかそれほど一般的ではないんですよね。

iOS5までとiOS6以降でだいぶ見た目がかわったので、まとめてみました。

iOS6でのUIDocumentInteractionController

実装方法はiOS6でもiOS5以前でも変わらないんですが、見た目はiOS6でがらっと変わりました。

iOS5までの見た目はこちら。 不透明なボードの上にシンプルなボタンが並びます。実直なUIですね。

iOS6での見た目はこちらです。

iOS6ではアイコンベースとなり、UIActivityViewControllerと同様の見た目になりました。 以前と比較すると、ベースのシートが半透明となり、背景を見ながら操作ができるようになりました。

さらに、iOS5までは「指定したファイルに対応したアプリ」だけが表示されていたんですが、iOS6からはファイルに相当するシステム機能も表示されるようになったので、機能的にも使い勝手がかなりよくなりました。

ユーザーがiOS6のアップデートをすれば、アプリ側で特に実装をかえなくてもあたらしい機能が使えるので、開発者としてはうれしいアップデートですね。

ファイルを送る側

さて、実装方法ですが、iOS5でもiOS6でも変わりません。 基本的にはファイルのNSURLを取得して、そのNSURLをもとにUIDocumentInteractionControllerを作成するだけです。 こちらはアプリが持っているjpegファイルを他のアプリに送信するコードです。

NSURL* url = [[NSBundle mainBundle] URLForResource:@"book" withExtension:@"jpg"];
    
if( url ){
    self.diController = [UIDocumentInteractionController interactionControllerWithURL:url];
        
    NSDictionary* dic = [NSDictionary dictionaryWithObject:@"fruit" forKey:@"tag"];
    self.diController.annotation = dic;
    self.diController.delegate = self;
        
    if ([self.diController presentOptionsMenuFromRect:self.view.frame
                                              inView:self.view animated:YES]){
    }
    else{
            NSLog(@"There is no app for this file.");
    }
}

(selfにUIDocumentInteractionControllerDelegateをつけておく必要があります。) もしUIDocumentInteractionControllerのpresentOptionsMenuFromRectでNOがかえってきたら、そのファイルに対応するアプリが一つもないということなので、何かメッセージでも表示しておきましょう。

また、annotation属性にDictionaryをつけておけば、ファイル以外の情報を送ることもできます。

ファイルを受け取る側

ファイルを受け取る側では、自分の受け取ることができるファイル形式をシステムに登録する必要があります。 Xcode4.5での設定方法はこちら。

TargetのInfoタブで「Document Type」を選び、受け取ることができるファイルの「Name」と「Type」を設定するだけです。 「Name」はわかりやすく適当につければいいんですが、Typesに設定する項目はUTIで指定します。

どんなUTIがあるのかは、Uniform Type Identifiers Referenceを確認してください。

情報を受けとった時の処理

ファイルを受け取ったときの処理は、OpenURLとほぼ同様です。 UIApplicationのこの関数で処理を行います。 application:(UIApplication )application didFinishLaunchingWithOptions:(NSDictionary )launchOptions application:(UIApplication )application openURL:(NSURL )url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation

受け取る側のアプリの起動状態によって呼ばれる関数がちょっと違い、アプリ自身が既に起動済みの場合にはopenURLだけが呼ばれますが、アプリがまだ起動されていない場合には、didFinishLaunchingWithOptionsとopenURLが続けて呼ばれます。 ただ、その場合にも最終的にはopenURLが呼ばれるので、実質的にはopenURLだけで処理をしていれば問題はないでしょう。

また、以前はapplication:(UIApplication )application handleOpenURL:(NSURL )urlで処理をしていましたが、現在ではopenURLで処理をすることが推奨されています。 openURLで処理をすると、呼び出し側のアプリのBundle Identifierを取得することができるのでhandleOpenURLより便利です。 また、annocationが取得できるのもopenURLだけです。

UIDocumentInteractionControllerの利点、欠点

UIDocumentInteractionControllerの一番の利点は、他のアプリの「URLSchema」などの情報を全く知らなくても実装できることです。 また、iOS5以下でも使用することができるのでOSバージョンをあまり気にせずに使えます。 ただ、ファイルを一つしか扱うことができない(複数のファイルをzip形式などにまとめて送信すれば別ですが)こと、独自拡張ができないことが欠点でしょうか。

サンプルソース

サンプルソースをGithubにおきました。 (OpenURL、UIDocumentInteractionController、UIActivityViewControllerを使ったファイル連携が実装されています。) SendDataDemo(情報を送る側) ReceiveDataDemo(情報を受け取る側)