##自己紹介
- フリーランスiOSエンジニア
- iOS / watchOS Sampler シリーズをつくっています
##2015年にお手伝いしたwatchOS案件
(一部だけお手伝い、非公開プロジェクトも含む)
##「それ、残念ながらできないんです・・・」
(企画の詳細は書けませんが・・・)
- ジャイロが必要な機能 × 2
- アプリが非アクティブになってもセンサの値を取り続ける必要がある機能 × 2
- タップ位置を知る必要があるインタラクション × ?
- ジョイスティック的な引っ張る系のUI × 2
- ウォッチ本体から音を鳴らす × ?
##watchOS 3 ではできるようになった!
- ジャイロが必要な機能 - Gyroscope access
- アプリが非アクティブになってもセンサの値を取り続ける必要がある機能 - Background support
- タップ位置を知る必要があるインタラクション - UITapGestureRecognizer
- ジョイスティック的な引っ張る系のUI - UIPanGestureRecognizer
- ウォッチ本体から音を鳴らす - Speaker Audio
(参考:API Diffsから見る watchOS 3 の新機能 - Qiita)
##本当にできるようになったのか?
- キーノート、あるいはドキュメントで見かけただけ
- 実際に試してみないと思わぬ制限があるかもしれない
##watchOS 3 を入れた Apple Watch 実機で「本当にできるようになったのか」試してみる
##検証1: Gyroscope access
##API自体は前からあった
let motionManager = CMMotionManager()
override func willActivate() {
super.willActivate()
let handler:CMGyroHandler = {(data: CMGyroData?, error: NSError?) -> Void in
// データ取得時の処理
}
if motionManager.isGyroAvailable {
motionManager.startGyroUpdates(to: OperationQueue.current()!, withHandler: handler)
} else {
// 利用不可の場合の処理
}
}
##が、
motionManager.isGyroAvailable
の戻り値が常に false
だった。
→ 事実上の非サポート だった
##WWDC16のキーノート
はっきり "Gyroscope Access" と書かれている
##watchOS 3 実機で試してみた
print("\(CMMotionManager().isGyroAvailable)")
##実行結果
##false
##→ watchOS 3 でも CMGyroData は Not Available!!!!
##????
そんなはずは・・・
##WWDC16のwatchOS関連セッションスライドを"gyro"で検索
- What's New in watchOS 3
- Architecting for Performance on watchOS 3
- Building Great Workout Apps
- Keeping Your Watch App Up to Date
- Quick Interaction Techniques for watchOS
- Designing Great Apple Watch Experiences
- Game Technologies for Apple Watch
##出てこない・・・
##思わぬ伏兵
##Health and Fitness with Core Motion (713)
スライドp49、動画では13分ぐらいから。
CMDeviceMotion が Apple Watch で利用可能!
##これが取れるならむしろ CMGyroData はいらない
##CMDeviceMotion から得られるデータ
##デバイスの角加速度
public var rotationRate: CMRotationRate { get }
- 回転の加速度
- ジャイロセンサより得られる
- 大昔に試したことがあるが、CMGyroDataとほぼ同じ値 (小数点第2位ぐらいまで一致)が得られた
##利用例:モーション検出
CMDeviceMotionから得られる 姿勢情報/オイラー角(加速度センサとジャイロから求められる) を利用して、テニスのフォアハンドとバックハンドのスウィングを自動検出
- 同セッションでサンプルが紹介されている
- どこかで話すか解説記事を書きます
##API自体は前からあった
let motionManager = CMMotionManager()
override func willActivate() {
super.willActivate()
let handler: CMDeviceMotionHandler = {(motion: CMDeviceMotion?, error: NSError?) -> Void in
// データ取得時の処理
}
if motionManager.isDeviceMotionAvailable {
motionManager.startDeviceMotionUpdates(to: OperationQueue.current()!, withHandler: handler)
} else {
// 利用不可の場合の処理
}
}
motionManager.isDeviceMotionAvailable
が必ず false
を返してきていた
##watchOS 3 実機で試してみた
##(デモ)
##検証1: Gyroscope access → watchOS 3 では可能!
##検証2: ウォッチ本体から音を鳴らす
##watchOS 2 からある WKAudioFilePlayer
- オーディオファイルを再生するクラス
- 要Bluetoothヘッドセット
##Bluetooth ヘッドセットを「Apple Watchに」ペアリングして音を聴く!?
##WWDC16のキーノート
Apple Watch のスピーカーから音を出せるようになった?
##AV Foundation on watchOS
- watchOS 3 から AVFoudation が使えるように!
- 全部のクラスが移行されるわけではないが、色々入っている
- AVAudioPlayerNode(オーディオファイル再生)
- AVAudioEngine(オーディオ処理諸々)
- AVSpeechSynthesizer(音声合成) 等々
(参考:API Diffsから見る watchOS 3 の新機能 - Qiita)
##watchOS 3 実機で試してみた
import Foundation
import AVFoundation
struct AudioEngine {
private let engine = AVAudioEngine()
private let player = AVAudioPlayerNode()
private var file: AVAudioFile?
init() {
setup()
}
private mutating func setup() {
// setup engine and player
engine.attach(player)
guard let fileURL = Bundle.main().urlForResource("drumLoop", withExtension: "caf") else {
fatalError("\"drumLoop.caf\" file not found.")
}
do {
let file = try AVAudioFile(forReading: fileURL)
self.file = file
engine.connect(player, to: engine.mainMixerNode, format: file.processingFormat)
}
catch {
fatalError("Could not create AVAudioFile instance. error: \(error).")
}
}
private func scheduleLoop() {
guard let file = file else {
fatalError("`file` must not be nil in \(#function).")
}
player.scheduleFile(file, at: nil) {
self.scheduleLoop()
}
}
// MARK: - Public
func start() {
// Schedule buffers on the player.
scheduleLoop()
// Start the engine.
do {
try engine.start()
}
catch {
fatalError("Could not start engine. error: \(error).")
}
player.play()
}
// Stop the engine
func stop() {
player.stop()
engine.stop()
}
func isPlaying() -> Bool {
return player.isPlaying
}
}
##(デモ)
##検証2: ウォッチ本体から音を鳴らす → watchOS 3 では可能!
##ここまでのまとめ
##watchOS 3 では
CMDeviceMotionでジャイロセンサの値、およびそれを利用した姿勢情報を取れるようになった!
→ ⌚️を利用したモーション認識が可能に!
##watchOS 3 では
AVAudioEngineが使えるようになった!
→ ⌚️から**「直接」音を出せる**ようになった!
次回予定:
- バックグラウンド機能の検証
- CPU負荷とか、いろいろ制約はあるっぽい
##ご清聴ありがとうございました!
本記事は、2016.7.1に開催された WWDC.next でのLT資料です。
※Appleによる公開リソースをもとに作成しています。