Today Extensionは通知センター内に表示するウィジェットを提供するエクステンションです。
iPhoneのモーションセンサが計測した歩数を表示するサンプルを作成しました。
https://github.com/imk2o/Try-AppExtensions
処理の流れ
- ビューコントローラがインスタンス化される
- ウィジェットのマージンを求める
- NCWidgetProviding#widgetMarginInsetsForProposedMarginInsets(_:)
- データを取得し、ウィジェットを更新する
- NCWidgetProviding#widgetPerformUpdateWithCompletionHandler(_:)
- ユーザアクションに応じ、アプリを起動する
- NSExtensionContext#openURL(_:completionHandler:)
widgetPerformUpdateWithCompletionHandler(_:)
データ取得等を行い、ウィジェットの更新を行うロジックを実装します。
更新完了時は必ず、以下のいずれかの値とともにcompletionHandler
を呼び出す必要があります。
- NCUpdateResult.Failed: エラーが発生した
- NCUpdateResult.NoData: 更新を行わなかった
- NCUpdateResult.NewData: 更新を行った
func widgetPerformUpdateWithCompletionHandler(completionHandler: ((NCUpdateResult) -> Void)) {
guard CMPedometer.isStepCountingAvailable() else {
completionHandler(.Failed)
return
}
// 今日の00:00から現時刻までの歩数を求め、これを表示する
let now = NSDate()
let calendar = NSCalendar.currentCalendar()
let dateComponents = calendar.components([NSCalendarUnit.Year, NSCalendarUnit.Month, NSCalendarUnit.Day], fromDate: now)
let startDate = calendar.dateFromComponents(dateComponents)
self.pedometer.queryPedometerDataFromDate(startDate!, toDate: now) { (data, error) in
if let _ = error {
completionHandler(.Failed)
} else if let steps = data?.numberOfSteps {
self.stepsLabel.text = "\(steps) steps"
completionHandler(.NewData)
} else {
completionHandler(.NoData)
}
}
}
widgetMarginInsetsForProposedMarginInsets(_:) (optional)
通常は通知センター内に一定のマージンを取った内側にウィジェットが表示されますが、このマージンを調整することができます。
アプリの起動
アプリへの導線を追加する場合は、UIViewController#extensionContext
のopenURL()
を利用します。
@IBAction func viewDidTap(sender: AnyObject) {
// URLスキームでアプリを起動
if let appURL = NSURL(string: "myapp://") {
self.extensionContext?.openURL(appURL, completionHandler: nil)
}
}
メモ
「高負荷な処理を行ってはいけない」や「横スクロールできてはいけない」等、いくつかのガイドラインに従い実装する必要があります。
参考
https://www.gaprot.jp/pickup/ios8/today-extension
http://sonson.jp/blog/2014/09/18/Widget/