koogawa blog

iOS、Android、foursquareに関する話題

【Tips】iOSでシェイクジェスチャーを検知する(Swift対応)

iPhoneのシェイクジェスチャー(振る動作)を検知する方法を説明します。

実装方法

まずは、シェイクジェスチャーを検知したいクラス*1canBecomeFirstResponder をオーバーライドして YES を返します。これは、シェイク動作を検知するためにファーストレスポンダになる必要があるためです。

Objective-C:

- (BOOL)canBecomeFirstResponder {
    return YES;
}

Swift:

override func canBecomeFirstResponder() -> Bool {
    return true
}

これで、シェイクジェスチャーを受け取る準備が整いました。

この状態でiPhoneを振ると、次のメソッドが呼ばれます。

Objective-C:

// シェイク開始
- (void)motionBegan:(UIEventSubtype)motion withEvent:(UIEvent *)event
{
    if (event.type == UIEventTypeMotion && event.subtype == UIEventSubtypeMotionShake)  {
        NSLog(@"Motion began");
    }
}

// シェイク完了
- (void)motionEnded:(UIEventSubtype)motion withEvent:(UIEvent *)event
{
    if (event.type == UIEventTypeMotion && event.subtype == UIEventSubtypeMotionShake) {
        NSLog(@"Motion ended");
    }
}

// シェイクがキャンセルされた
- (void)motionCancelled:(UIEventSubtype)motion withEvent:(UIEvent *)event
{
    if (event.type == UIEventTypeMotion && event.subtype == UIEventSubtypeMotionShake) {
        NSLog(@"Motion cancelled");
    }
}

Swift:

override func motionBegan(motion: UIEventSubtype, withEvent event: UIEvent?) {
    if event?.type == UIEventType.Motion && event?.subtype == UIEventSubtype.MotionShake {
        // Motion began
    }
}

override func motionEnded(motion: UIEventSubtype, withEvent event: UIEvent?) {
    if event?.type == UIEventType.Motion && event?.subtype == UIEventSubtype.MotionShake {
        // Motion ended
    }
}

override func motionCancelled(motion: UIEventSubtype, withEvent event: UIEvent?) {
    if event?.type == UIEventType.Motion && event?.subtype == UIEventSubtype.MotionShake {
        // Motion cancelled
    }
}

引数として UIEvent が渡されるので、そのプロパティである UIEventTypeUIEventSubtype を見てシェイクジェスチャーであるかどうかの判定をしています。

通常は motionBeganmotionEnded の順に呼ばれます。

iPhoneを軽く振っただけでは motionBegan しか呼ばれず、一定時間放置すると motionCancelled が呼ばれるようです。

サンプルコード

注意点

  • iOS 3 以降で使用できます

応用できそうなアプリ

  • シェイクすることで音が鳴る楽器アプリ
  • iPhoneを振ることで何かを競うゲーム
  • シェイク動作によるリセット処理

参考にさせて頂いたリンク

*1:UIViewControllerなど、UIResponderクラスを継承している必要があります