その後のその後

iOSエンジニア 堤 修一のブログ github.com/shu223

【iOS8】App Extension の実装方法 その1:Action

App Extension とは?

App Extension (Extensions) は、iOS 8 から導入される、新しいアプリ間連携のしくみです。



iOS では、以下の 6種類の Extension point *1を利用することができます。

  • Today
  • Share
  • Action
  • Photo Editing
  • Storage Provider
  • Custom keyboard


大まかな仕組みは同じなのですが、見た目/機能は Extension point によって色々と違いがあり、実装方法も違ってくる(部分もある)ので、個別に説明していきたいと思います。


まずは一番説明しやすい "Action" から。

1. ターゲットを作成する

Xcode の [File] > [New] > [Target] から、[Application Extension] > [Action Extension] を選択します。


(※Xcode6のスクショではありません。App Extension Programming Guide の図3-1 です。)


ここでは [Action Type] は [View Controller] を選択します。

2. Extension の実装

Extension が起動されたときの見た目や挙動を実装します。


たとえば、ImageInverter サンプルでは、`viewDidLoad` で入力画像を反転して表示するように実装されています。

// extensionContextから入力アイテムを取得
NSExtensionItem *imageItem = [self.extensionContext.inputItems firstObject];

// NSItemProviderを取得
NSItemProvider *imageItemProvider = [[imageItem attachments] firstObject];

if([imageItemProvider hasItemConformingToTypeIdentifier:(NSString *)kUTTypeImage]){

    // 入力画像を取得    
    [imageItemProvider loadItemForTypeIdentifier:(NSString *)kUTTypeImage options:nil completionHandler:^(UIImage *image, NSError *error) {
        
        if(image){
            
            dispatch_async(dispatch_get_main_queue(), ^{
                
                // 画像を反転させる
                UIImage* invertedImage = [self invertedImage:image];
                
                // 表示
                [imageView setImage:invertedImage];
            });
            
        }
    }];
    
}

(説明用に簡略化しています。また `invertedImage` メソッドのソースは省略。)



そして、done ボタン押下で編集済みアイテムを返します。

-(void)done:(id)sender{
    
    // 編集済みのNSExtensionItemオブジェクトを作成
    NSExtensionItem *extensionItem = [[NSExtensionItem alloc] init];
    [extensionItem setAttachments:@[[[NSItemProvider alloc] initWithItem:[self.imageView image]
                                                          typeIdentifier:(NSString*)kUTTypeImage]]];
    
    // Host appに返す
    [self.extensionContext completeRequestReturningItems:@[extensionItem] completionHandler:nil];
}

Host appの実装

Extension を呼び出す側のアプリの実装です。


ボタン押下時に UIActivityViewController を表示する、というのは従来と同じなのですが、完了ハンドラの引数で、Extention から返ってきたアイテムを受け取れるようになっています。


ImageInverter サンプルでは、下記のように画像を取り出して表示しています。

- (IBAction)share:(id)sender {
    
    UIActivityViewController *activityViewController = [[UIActivityViewController alloc] initWithActivityItems:
  @[[self.imageView image]]
                                                                                         applicationActivities:nil];
    
    [activityViewController setCompletionWithItemsHandler:^(NSString *activityType, BOOL completed, NSArray *returnedItems, NSError * error){
        
        // 返ってきたアイテムを取得
        NSExtensionItem* extensionItem = [returnedItems firstObject];
        NSItemProvider* imageItemProvider = [[extensionItem attachments] firstObject];

        // 画像を取り出して表示
        if([imageItemProvider hasItemConformingToTypeIdentifier:(NSString *)kUTTypeImage]){
            
            [imageItemProvider loadItemForTypeIdentifier:(NSString *)kUTTypeImage
                                                 options:nil
                                       completionHandler:^(UIImage *item, NSError *error) {
                                           
                                           if(item && !error){
                                               
                                               dispatch_async(dispatch_get_main_queue(), ^{
                                                   [self.imageView setImage:item];
                                               });
                                           }
                                       }];
        }
    }];
    
    [self presentViewController:activityViewController animated:YES completion:nil];
}

(説明用に簡略化しています。)

実行時の注意点

新しい機能なので、 UIActivityViewController が立ち上がってどうすればいいか一瞬戸惑うのですが、初回のみ [More] から今回追加した Extension を有効にして、UIActivityViewController を立ち上げ直す必要があります。


InvertImageサンプル自体は公開されているものの、Xcode6はNDA下にあるため、実行結果のスクショはここでは掲載を控えておきます。

*1:OS X は4種類