[iOS 8] NSExtension系APIに触れてみる

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

NSExtension系API

iOS 8 及び OS X 10.10 より、app extension が追加されました。
自分が作った以外のアプリに向けて、拡張機能を提供することができるようになったのです。
何らかの拡張機能を作るために必要となってくるのが、いわゆる NSExtension 系のクラスなどです。 この記事では、その概要に触れてみようと思います。

NSExtensionContext & NSExtensionItem

データを、host app(拡張機能を呼び出すアプリ)とやりとりする時に欠かせないのが、NSExtensionItem クラスです。
画像やテキスト等様々なデータを保持するよう記述することができます。

また、NSExtensionContext クラスは、extension が実行されるコンテキストを定義するためのクラスです。
主な用途しては、inputItems プロパティを用いて、NSExtensionItemのインスタンスに対し、host app から受け渡されたアイテムを受け渡すことなどです。

Action Extension を作成した際に作られる ViewController の .m ファイルには、予め以下のようなコードが書かれています(一部省略)。

- (void)viewDidLoad {
    [super viewDidLoad];
    BOOL imageFound = NO;
    for (NSExtensionItem *item in self.extensionContext.inputItems) {
        for (NSItemProvider *itemProvider in item.attachments) {
            if ([itemProvider hasItemConformingToTypeIdentifier:(NSString *)kUTTypeImage]) {
                __weak UIImageView *imageView = self.imageView;
                [itemProvider loadItemForTypeIdentifier:(NSString *)kUTTypeImage options:nil completionHandler:^(UIImage *image, NSError *error) {
                    if(image) {
                        [[NSOperationQueue mainQueue] addOperationWithBlock:^{
                            [imageView setImage:image];
                        }];
                    }
                }];
                
                imageFound = YES;
                break;
            }
        }
        
        if (imageFound) {
            break;
        }
    }
}

4,5行目に注目。

for (NSExtensionItem *item in self.extensionContext.inputItems) {
   for (NSItemProvider *itemProvider in item.attachments) {

inputItems を取り出している部分で、extensionContext プロパティの記述を見つけることができます。
これを定義しているのは、UIViewController.h です。

@property (nonatomic,readonly,retain) NSExtensionContext *extensionContext NS_AVAILABLE_IOS(8_0);

UIViewController の extensionContext プロパティは、NSExtensionContext クラスから作成されたものであることがわかります。

もう一度上記のコードを見てみましょう。

for (NSExtensionItem *item in self.extensionContext.inputItems) {
   for (NSItemProvider *itemProvider in item.attachments) {

extension のコンテキストから、inputItemsプロパティを使い、host app から渡されたアイテムを取り出しています。その後 attachments プロパティを用いて NSItemProvider 型のオブジェクトとして次の処理に渡しています。

まとめ

いかがだったでしょうか。
NSExtension 系の API は app extension には欠かせないものです。
どんどん使って、個性的な extension を公開していきましょう!