注意: beta 5時点での情報です
iOS8で追加される待望のApp Extensionですが,あくまでExtensionなのでContaining appを呼び出したくなることがあると思います. App Extension Programming Guideにもあるように,App ExtensionとContaining appとの連携にはShared resourcesのほかにOpen URLを利用します. Open URLというと従来より形式化された手法ですので,とくにはまりどころは無いと思っていたのですが,はまりどころがあったので紹介させていただきます.
App ExtensionにはUIApplication
が無い
Open URLといえばご存知のようにUIApplication
を取得すればお気楽に実装できるのですが,App ExtensionにはUIApplication
のopenURL:
メソッドが存在しません.
// UIApplication.h より抜粋 - (BOOL)openURL:(NSURL*)url NS_EXTENSION_UNAVAILABLE_IOS("");
見事に隠されてますね. したがって,Open URLを実装したければ,別の方法を取る必要があります.
App ExtensionではNSExtensionContext
を使う
ここで登場するのがNSExtensionContext
のopenURL:completionHander:
です.
Share Extensionの場合,エンドポイントとなるSLComposeServiceViewController
がNSExtensionContext
を持っていますので,以下のように実装することが考えられます.
// `NSExtensionContext`を使ってopenURLする NSURL *URL = [NSURL URLWithString:@"myapp://login"]; [self.extensionContext openURL:URL completionHandler:^(BOOL success) { // successが`YES`なら成功 }];
これで安心と思いきや,そうは問屋がおろしません.
なんだそれは!と思われるかもしれませんが,openURL:completionHandler:
はToday Extension以外で動作しません.
動作を確認してみたとき,success
にNO
が得られて,てっきりContaining appを呼び出すCustom URL Schemeを間違っているのかと思いましたが,どうやらそうではないようです.
それでも絶対Open URLしたい!
我々にはUIWebView
があります.
Zero RectのUIWebView
を作成し,開きたいURLをloadRequest:
すると当然のように動作します.
もちろんロードが完了するまでUIWebView
を保持する必要がありますのでSLComposeServiceViewController
に貼り付けておきましょう.
余談ですが,SLComposeServiceViewController
は特別な存在なのかなあと思ったら,わりと普通にUIViewController
のサブクラスです.
// Share Extensionでの真のOpen URL UIWebView *webView = UIWebView.new; [self.view addSubview:webView]; // ロード完了まで保持しておきたいので適当に貼り付けておく NSURL *URL = [NSURL URLWithString:@"myapp://login"]; [webView loadRequest:[NSURLRequest requestWithURL:URL]];
まとめ
UIWebView
こそ人類に残された最後の希望.