エンジニア

Action Extensionsの実装について

投稿日:2015年1月30日 更新日:

今回エンジニアブログを担当する戸田です。

今回はiOS8で新たに追加されたApp Extensionsについて紹介したいと思います。App Extensionsは、アプリの一部機能を他のアプリから利用できる仕組みになります。iOSで使用できる主な機能は次の通りになります。

  • Today
  • Share
  • Action
  • Photo Editing
  • Document Provider
  • Custom Keyboard

今回はその中でも「Action」について紹介します。

Action Extensionの実装

1.前準備

前準備としてAction Extensionを追加する為のプロジェクトを作成します。

Xcodeを起動して、メニューの「File」>「New」>「Project...」を選択します。

ActionExtensions-01

テンプレートから作成するプロジェクトを選び、「Next」を選択ます。

ActionExtensions-02

次に以下のプロジェクト設定を行い「Next」を選択します。

  • Product Name
  • Organization Name
  • Organization Identifier
  • Languag
  • Devices

ActionExtensions-03

プロジェクトを保存する先を決めて、「Create」を選択します。

2.Action Extensionのターゲットを作成

作成したプロジェクトにApp Extensionsのターゲットを追加します。

メニューの「File」>「New」>「Terget...」を選択します。

ActionExtensions-05

テンプレートの「iOS」>「Application Extension」>「Action Extension」を選んで「Next」を選択ます。

ActionExtensions-06

次に以下のターゲット設定を行い「Next」を選択します。

  • Product Name
  • Organization Name
  • Languag
  • Action Type
  • Project
  • Embed in Application

ActionExtensions-07

Action Extensionのschemeを有効にするかを聞かれているので、「Active」を選択して有効にします。

ActionExtensions-08

3.Action Extensionの実装

デフォルトで作成されたコードを一部変更して説明していきます。

まず、「ActionViewController」の「viewDidLoad」メソッドを以下のように変更します。

- (void)viewDidLoad {
    [super viewDidLoad];

    __block UIImage *compositeImage = nil;
    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:^{
                            CGSize size = image.size;

                            UIGraphicsBeginImageContextWithOptions(size, 0.0f, [[UIScreen mainScreen] scale]);

                            [compositeImage drawInRect:CGRectMake(0, 0, size.width, size.height)];
                            [image drawInRect:CGRectMake(0, 0, size.width, size.height)];

                            compositeImage = UIGraphicsGetImageFromCurrentImageContext();

                            UIGraphicsEndImageContext();

                            [imageView setImage:compositeImage];

                        }];
                    }
                }];
            }
        }
    }
}

Action Extensionがコールされる際に一緒に渡されるObjectの取得は、コードの5〜9行目で行っています。

続いて、「done」メソッドを以下のように変更します。

- (IBAction)done {
    NSExtensionItem *extensionItem = [[NSExtensionItem alloc] init];
    [extensionItem setAttachments:@[[[NSItemProvider alloc] initWithItem:[self.imageView image]
                                                          typeIdentifier:(NSString*)kUTTypeImage]]];

    [self.extensionContext completeRequestReturningItems:@[extensionItem] completionHandler:nil];
}

コール元にObjectを返す時は、NSExtensionItemに格納する必要があるため、「done」メソッド内の1〜3行目で行っています。

4.info.plistの設定

Action Extensionの定義をinfo.plistで行います。また、デフォルト設定で以下のようになっています。

ActionExtensions-09

「NSExtensionActivationRule」内でAction Extensionへの受け渡しするオブジェクトの定義を行います。今回はKeyに「NSExtensionActivationSupportsImageWithMaxCount」、Valueに「2」を設定します。

※「NSExtensionActivationRule」のValueが「TRUEPREDICATE」になっていますが開発時専用になるため、Appleの審査でリジェクトの対象になります。

ActionExtensions-10

5.Action Extensionのコール元を実装

プロジェクトの「SampleAppExtensionHost」配下にある「Main.storyboard」と「ViewController.m」を以下のようにします。

Main.storyboard

ActionExtensions-11

ViewController.m

#import <MobileCoreServices/MobileCoreServices.h>
@interface ViewController ()

@property (strong, nonatomic) IBOutlet UIImageView *beforeImage;
@property (strong, nonatomic) IBOutlet UIImageView *afterImage;
@property (strong, nonatomic) IBOutlet UIImageView *overlayImage;

@end
- (IBAction)actionTopButton:(UIButton *)sender {

    UIActivityViewController *activityViewController = [[UIActivityViewController alloc] initWithActivityItems:@[[self.beforeImage image], [self.overlayImage image]]
                                                                                         applicationActivities:nil];

    [activityViewController setCompletionWithItemsHandler:^(NSString *activityType, BOOL completed, NSArray *returnedItems, NSError * error){

        NSExtensionItem* extensionItem = [returnedItems firstObject];
        NSItemProvider* itemProvider = [[extensionItem attachments] firstObject];

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

            [itemProvider loadItemForTypeIdentifier:(NSString *)kUTTypeImage
                                            options:nil
                                  completionHandler:^(UIImage *image, NSError *error) {

                                          [[NSOperationQueue mainQueue] addOperationWithBlock:^{

                                              [self.afterImage setImage:image];

                                          }];
                                  }];
        }
    }];

    [self presentViewController:activityViewController animated:YES completion:nil];

}

Action Extensionのコール及び引き渡すObjectの処理は、actionTopButtonメソッド内の3・4行目で行っています。
Action Extensionで合成されたObjectを受け取る処理は、actionTopButtonメソッド内の6〜24行目で行っています。

6.実行

Schemeの「SampleAppExtensionHost」を選択して、メニューの「Product」>「Run」を選択します。
アプリが起動後に「合成」をタップすると「ActivityViewController」が表示され、「SampleAppExtension」のアイコンをタップすると2つの画像が合成・表示されます。その後、「Done」をタップすると呼び元に合成画像が渡され表示されます。

ActionExtensions-12 ActionExtensions-13 ActionExtensions-14 ActionExtensions-15

以上が「Action Extensionの実装について」の紹介になります。

採用情報

ワンダープラネットでは、一緒に働く仲間を幅広い職種で募集しております。

-エンジニア
-, ,

© WonderPlanet Inc.