今回エンジニアブログを担当する戸田です。
今回は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...」を選択します。
テンプレートから作成するプロジェクトを選び、「Next」を選択ます。
次に以下のプロジェクト設定を行い「Next」を選択します。
- Product Name
- Organization Name
- Organization Identifier
- Languag
- Devices
プロジェクトを保存する先を決めて、「Create」を選択します。
2.Action Extensionのターゲットを作成
作成したプロジェクトにApp Extensionsのターゲットを追加します。
メニューの「File」>「New」>「Terget...」を選択します。
テンプレートの「iOS」>「Application Extension」>「Action Extension」を選んで「Next」を選択ます。
次に以下のターゲット設定を行い「Next」を選択します。
- Product Name
- Organization Name
- Languag
- Action Type
- Project
- Embed in Application
Action Extensionのschemeを有効にするかを聞かれているので、「Active」を選択して有効にします。
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で行います。また、デフォルト設定で以下のようになっています。
「NSExtensionActivationRule」内でAction Extensionへの受け渡しするオブジェクトの定義を行います。今回はKeyに「NSExtensionActivationSupportsImageWithMaxCount」、Valueに「2」を設定します。
※「NSExtensionActivationRule」のValueが「TRUEPREDICATE」になっていますが開発時専用になるため、Appleの審査でリジェクトの対象になります。
5.Action Extensionのコール元を実装
プロジェクトの「SampleAppExtensionHost」配下にある「Main.storyboard」と「ViewController.m」を以下のようにします。
Main.storyboard
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」をタップすると呼び元に合成画像が渡され表示されます。
以上が「Action Extensionの実装について」の紹介になります。