Today Widget を調査してみた。

iOS8からはToay View(カレンダー、株価、etc….)に Widgetを追加できます。

Widgetの特徴

  • Widget上にアプリを常駐させる事ができます。
  • 制約はありますが、Widgetでは通常のアプリで出来る事が殆ど実現できます。
  • LockスクリーンからもWidgetが使えます。たとえば、Lockをはずさないで、Widget経由でアプリを起動させる事もできます。

Widgetの制約

  • 高さが大きくなりすぎるのは,Todayの中身が巨大になってしまうのでダメ.あまり大きいビューコントローラを利用すると自動的にサイズを切られる。
  • widgetの中にスクロールビューをいれるのはダメ.スクロール操作は一切処理できない。
  • キーボードが使えない。
  • タップイベントを取ることはできる。
  • 配布はアプリケーションにバンドルする形式で行う。
  • アプリケーションとのデータ共有はApp Groupを使って行う。
  • Extensionでは,UIApplicationクラスを利用できない。 アプリケーションを起動するときは,openURLを使うが,UIApplicationではなく,NSExtensionContextクラスのメソッドを利用する。

こんなことが出来ます。

  • Widget上からゲームを起動できます。
  • (例)DQMSLのイベント情報カレンダーをWidgetで実装して、タップするとゲームが起動する。(サンプル参照)
  • WidgetにWebViewをはれます。
  • 動画も再生できます。イベント告知ができるでしょう。
  • MPMoviePlayerController,AVFoundation等を用いる

実装上の注意点

CocoaPods

WidgetはホストアプリとはTargetが異なるので、Podfileに少々追記が必要になります。

target :(widgetのTarget名), :exclusive => true do
    pod 'ASIHTTPRequest'
end

コーディング注意点

viewDidLoad時にWidgetのサイズを指定しないと、viewがつぶれて見えなくなる。

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view from its nib.
    
    //このサイズを指定しないと、Widgetが潰れ見えなくなる。
    self.preferredContentSize = CGSizeMake(320, 300);
}

defaultではwidgetに余白が設定されている。 余白を無くしたい場合は、以下のコードを挿入する。

-(UIEdgeInsets)widgetMarginInsetsForProposedMarginInsets(UIEdgeInsets)defaultMarginInsets
{
    return UIEdgeInsetsZero;
}

AppExtensionではUIApplicationのOpenURLは使えないので下記方法でURLスキームを利用します。

 [self.extensionContext openURL:myURL completionHandler:nil];

UIWebViewを利用してURLスキームもできます。(この手法だと、lockスクリーンからアプリを起動することが出来ません。)

 NSURL *myURL = [NSURL URLWithString:urlstring];
    UIWebView *webView = UIWebView.new;
    [self addSubview:webView];
    [webView loadRequest:[NSURLRequest requestWithURL:myURL]];

Sampleコード

カレンダー風widgetサンプル