Download - App extension for iOS

Transcript
Page 1: App extension for iOS

App Extension

2014/6/20@TachibanaKaoru

Page 2: App extension for iOS

この書類は、Apple社が公開している情報をもとに作成しています。

Page 3: App extension for iOS

Agenda

• About

• What is App Extension

• How to make App Extension

• How to share data Container and Extension

• App Group and Shared Container

• How to share codes between Container and Extension

• Information

Page 4: App extension for iOS

About

• @TachibanaKaoru

• 渋谷のgenesix(VOYAGE GROUP)という会社で iOS エンジニアをしています。

• Blog : http://www.toyship.org/

• WWDCの参加は2010が最後でした。

• それ以来行けていません……。

Page 5: App extension for iOS

What is App Extension

• iOS8から導入された、アプリ間の連携の仕組み。

• それに加え、Notification Centerに表示するWidget機能やサードパーティ製キーボードも含まれています

• 今日はそれぞれのApp Extensionの詳細には踏み込まず、App Extension全体に関連する項目を中心にすすめます

Page 6: App extension for iOS

What is App Extension

• App Extensions

• Today (iOS/OS X)

• Share (iOS/OS X)

• Action (iOS/OS X)

• Photo Editing (iOS)

• Finder (OS X)

• Storage Provider (iOS)

• Custom keyboard (iOS)

Page 7: App extension for iOS

What is App Extension

• App Extensions

• Today (iOS/OS X)

• Share (iOS/OS X)

• Action (iOS/OS X)

• Photo Editing (iOS)

• Finder (OS X)

• Storage Provider (iOS)

• Custom keyboard (iOS)

Page 8: App extension for iOS

What is App Extension

• App Extensions

• Today (iOS/OS X)

• Share (iOS/OS X)

• Action (iOS/OS X)

• Photo Editing (iOS)

• Finder (OS X)

• Storage Provider (iOS)

• Custom keyboard (iOS)

Page 9: App extension for iOS

What is App Extension

• App Extensions

• Today (iOS/OS X)

• Share (iOS/OS X)

• Action (iOS/OS X)

• Photo Editing (iOS)

• Finder (OS X)

• Storage Provider (iOS)

• Custom keyboard (iOS)

Page 10: App extension for iOS

What is App Extension

• App Extensions

• Today (iOS/OS X)

• Share (iOS/OS X)

• Action (iOS/OS X)

• Photo Editing (iOS)

• Finder (OS X)

• Storage Provider (iOS)

• Custom keyboard (iOS)

Page 11: App extension for iOS

How to make App Extension

• Extensionは、アプリのターゲットとして追加される

• ExtensionはContaining Appに含まれて単体でリリースすることはできない

Page 12: App extension for iOS

How to make App Extension

• Extensionは、Contaning Appと同じipaに含まれてリリースされますが、Extensionは、Contaning Appアプリとしては全く別の存在です。

• アプリから利用するサンドボックス、設定、メモリ空間、のすべてで異なります。

• (ここのデータ共有する方法については後ほど説明します)

Page 13: App extension for iOS

How to make App Extension

• Containing App(本体アプリ)にターゲットを追加

• Extensionごとにターゲットのテンプレートがあるので、自分の作成したいExtensionを選択

Page 14: App extension for iOS

How to make App Extension

• Extensionをターゲットとして追加すると、自動的にターゲットのinfo.plistと、Extensionの動作の中心となるViewControllerクラスのファイルが作成されます。

• 基本的な動作は、そのViewControllerクラスを拡張するのみ

Page 15: App extension for iOS

How to make App Extension

• Extensionは、Containing App(本体アプリ)とは別プロセスとなるため、独自のBundle Identifierを設定します。

• ただし、Containing AppとExtensionのBundle Identifierは、同じPrefixを持つ必要があります。

• 例:Containing App: org.toyship.chat

• 例:Extension:org.toyship.chat.widget

Page 16: App extension for iOS

How to make App Extension

• Extensionで使えないAPIがあります。

• NS_EXTENSION_UNAVAILABLE_IOS

+ (UIApplication *)sharedApplication NS_EXTENSION_UNAVAILABLE_IOS("Use view controller based solutions where appropriate instead."); !@property(nonatomic,assign) id<UIApplicationDelegate> delegate; !- (void)beginIgnoringInteractionEvents NS_EXTENSION_UNAVAILABLE_IOS(""); - (void)endIgnoringInteractionEvents NS_EXTENSION_UNAVAILABLE_IOS(""); - (BOOL)isIgnoringInteractionEvents; !

@property(nonatomic,getter=isIdleTimerDisabled) BOOL idleTimerDisabled; !- (BOOL)openURL:(NSURL*)url NS_EXTENSION_UNAVAILABLE_IOS(""); - (BOOL)canOpenURL:(NSURL *)url NS_AVAILABLE_IOS(3_0);

Page 17: App extension for iOS

How to make App Extension

• UIApplication.h

+ (UIApplication *)sharedApplication NS_EXTENSION_UNAVAILABLE_IOS("Use view controller based solutions where appropriate instead."); !@property(nonatomic,assign) id<UIApplicationDelegate> delegate; !- (void)beginIgnoringInteractionEvents NS_EXTENSION_UNAVAILABLE_IOS(""); - (void)endIgnoringInteractionEvents NS_EXTENSION_UNAVAILABLE_IOS(""); - (BOOL)isIgnoringInteractionEvents; !

@property(nonatomic,getter=isIdleTimerDisabled) BOOL idleTimerDisabled; !- (BOOL)openURL:(NSURL*)url NS_EXTENSION_UNAVAILABLE_IOS(""); - (BOOL)canOpenURL:(NSURL *)url NS_AVAILABLE_IOS(3_0);

Page 18: App extension for iOS

How to make App Extension

• UIApplication-sharedApplicationが使えない

• UIApplication-openURLも使えない

• UIViewControllerの新しいpropertyとして、NSExtensionContextが追加されていて、Extensionではこのオブジェクトが取得できます。

• このクラスが、Hostアプリ-Extensionのデータのやり取りやopenURLをサポートします。

Page 19: App extension for iOS

How to make App Extension

• NSExtensionContext

@interface NSExtensionContext : NSObject !// HostアプリからExtensionに渡される入力データ @property(readonly, copy, NS_NONATOMIC_IOSONLY) NSArray *inputItems; !// Hostアプリ側の処理が完了した時によばれる関数。終了時のBlockつき。これがよばれると、UIViewControllerは終了する。 - (void)completeRequestReturningItems:(NSArray *)items completionHandler:(void(^)(BOOL expired))completionHandler; !// Hostアプリが処理をキャンセルしたときによばれる - (void)cancelRequestWithError:(NSError *)error; !// Asks the host to open an URL on the extension's behalf - (void)openURL:(NSURL *)URL completionHandler:(void (^)(BOOL success))completionHandler; !@end

Page 20: App extension for iOS

How to make App Extension

NSExtensionContextで行われるデータの受け渡し

Page 21: App extension for iOS

How to make App Extension

• Extension内でNSExtensionContext経由でopenURLを実行

- (IBAction)openSomething:(id)sender { [self.extensionContext openURL:[NSURL URLWithString:@"http://www.apple.com/"] completionHandler:nil]; !}

Page 22: App extension for iOS

How to make App Extension - Today

• 「Today Extension」ターゲットを追加すると、UIViewControllerが自動生成される。

• Storyboardの利用も可能

Page 23: App extension for iOS

How to make App Extension - Today

• Today Extensionでは、表示領域が制限される

• Widgetの縦サイズを変更することは可能だが、デバイスの縦サイズが上限となっている

• UIScrollViewはおくべきでない

• Today Extensionではキーボード入力が不可となっているため、touch/gestureイベントのみで操作できるように実装する

Page 24: App extension for iOS

How to make App Extension - Share

• 「Share Extension」ターゲットを追加すると、SLComposeServiceViewControllerが自動生成される

• Share用のDialogが用意されているため、実装が容易

Page 25: App extension for iOS

How to make App Extension - Keyboard

• 「Custom Keyboard」ターゲットを追加すると、UIInputViewControllerが自動生成される。

• 独自キーボード領域の描画・処理を行うためのViewController

Page 26: App extension for iOS

How to make App Extension - Keyboard

• UIInputViewControllerで、独自キーを設定- (void)viewDidLoad { [super viewDidLoad]; // 独自キーボードボタンを設定する。 UIButton* button = [UIButton buttonWithType:UIButtonTypeCustom]; button.frame = CGRectMake(0, 0, 100, 100); [button addTarget:self action:@selector(inputSomething:) forControlEvents:UIControlEventTouchUpInside]; [self.view addSubview:button]; // 「次のキーボードへ」ボタンを設定する。 self.nextKeyboardButton = [UIButton buttonWithType:UIButtonTypeSystem]; [self.nextKeyboardButton setTitle:NSLocalizedString(@"Next Keyboard", @"Title for 'Next Keyboard' button") forState:UIControlStateNormal]; [self.nextKeyboardButton sizeToFit]; self.nextKeyboardButton.translatesAutoresizingMaskIntoConstraints = NO; [self.nextKeyboardButton addTarget:self action:@selector(advanceToNextInputMode) forControlEvents:UIControlEventTouchUpInside]; [self.view addSubview:self.nextKeyboardButton]; }

Page 27: App extension for iOS

How to make App Extension - Keyboard

• 文字入力はUIInputViewControllerのtextDocumentProxyメンバー経由で実行する

-(void)inputSomething:(id)sender{ // 好きな文字を入力する

[self.textDocumentProxy insertText:@"🍎"]; }

Page 28: App extension for iOS

How to share data Container and Extension

• Containing App とExtension間のデータをどのように共有すべきか

• 今までのアプリ間データ共有のKeychainも使えますが、もっといい仕組みが用意されています。

Page 29: App extension for iOS

How to share data Container and Extension

• Shared Container

Page 30: App extension for iOS

App Group and Shared Container

• App Groupとは

• iOS8から導入された、アプリ間のデータ共有システム

• App Groupを設定することによって、Shared Containerが利用可能となる

Page 31: App extension for iOS

App Groupの設定

• iOS Dev CenterでGroup IDを設定

• 例:group.org.toyship.chatter

• その後、プロジェクトのCapabilityで App Groupをonにする

• iOS Dev Centerで設定したGroup IDを選択

• Entitlementファイルが自動生成される

• Container AppとExtensionの両方に対して設定してください

Page 32: App extension for iOS

App Group and NSUserDefaults

• App Group設定後、NSUserDafaultsでsharedDefaultsが利用可能となる

NSUserDefaults *sharedDefaults = [[NSUserDefaults alloc] initWithSuiteName:@"group.org.toyship.kaomoji"]; NSString* strValue = [sharedDefaults valueForKey:@"Neko"];

Page 33: App extension for iOS

KeychainとApp Groupの比較

• 対応OSバージョンが異なる

• App Groupは8.0以降

• 保存データの柔軟性

• App Groupでは、NSUserDefaults、CoreData、ファイルが対応可能

• 情報を共有できるアプリの範囲が制限できる

• Keychainの場合には、同じベンダーのすべてのアプリで共有できることになるが、App Groupの場合には共有できる範囲を制限できる

Page 34: App extension for iOS

How to share codes between Container and Extension

• Containing AppとExtensionでソースコードを共有するには

Page 35: App extension for iOS

How to share codes between Container and Extension

• 共用のフレームワークとして、Embedded Frameworksを作ることができる。

• ただし、このフレームワークはContainer AppとExtensionの間の共有しかできず、他のアプリなどでは使えない。

• Extensionで使えないコードはEmbedded Frameworksの中でも使えない。

Page 36: App extension for iOS

Information

• Extensionは、現時点ではまだ不安定な点もあり、実装をすすめる際にはそれに留意する必要があります

Page 37: App extension for iOS

Information - NSLog

• Extensionは別プロセスになっており、DebuggerがAttach Processできていないため、NSLogが出力されない

• 下記の情報では成功した人もいるようです

• http://stackoverflow.com/questions/24031612/how-to-debug-ios-8-extensions-with-nslog?rq=1

!

Page 38: App extension for iOS

Information - Notify to users

• 実際にExtension実装をしても、ユーザー環境でonにされないとExtensionが使われない。

• on/offの設定がわかりにくく、せっかくExtensionを実装してもユーザーに気がついてもらえない可能性がある。

Page 39: App extension for iOS

Fin