😬

[iOS]ButtonをTapしたときに効果音を再生し、連続Tapにも対応する

2024/08/17に公開

概要

AVAudioPlayerplay() methodを呼ぶことで、Buttonをタップしたときに効果音を流す機能を実装できる。
素直にplay()を呼ぶだけでは、連続でタップしたときに、直前のタップによる効果音が再生中なら、新たにタップしたときの効果音は再生されない。
play()を呼ぶ前に、再生時間を0にセットすることで、連続したタップでも、毎回、効果音を再生できる。

背景

Buttonをタップしたときに、効果音を再生したいという要望がある。
AVAudioPlayerを使用することで、以下のように実装できる。

class ViewController: UIViewController {
    let audioPlayer: AVAudioPlayer? = {
        // Assetsに登録した音源の読み込み
        let data = NSDataAsset(name: "SampleSound")
        
        // 音源の登録
        let player = try? AVAudioPlayer(data: data!.data)
        
        player?.prepareToPlay()
        return player
    }()

    
    let button = UIButton()
    override func viewDidLoad() {
        super.viewDidLoad()
        setupView()
    }
    
    // Buttonの見た目とGestureの登録
    private func setupView() {
        view.addSubview(button)
        button.frame = CGRect(x: 100, y: 100, width: 200, height: 100)
        button.backgroundColor = .blue
        button.setTitle("tap Here", for: .normal)
        button.addTarget(nil, action: #selector(didTap), for: .touchUpInside)
    }
    
    // Buttonがタップされた時に呼ばれる
    @objc func didTap() {
        // 音源を再生する
        audioPlayer?.play()
    }
}

問題

上記の実装では、再生中の効果音が鳴り終わる前に連続してタップしたときに、一度しか効果音が再生されない。
(e.g. 1秒で3回タップしても、最初の一度しか効果音が流れない)

解決策

毎回、音源の再生時間を0にすることで、連続でタップされても、毎回効果音を再生できる。

    @objc func didTap() {
        // 再生時間を最初に戻す
        audioPlayer?.currentTime = 0
        // 音源を再生する
        audioPlayer?.play()
    }

連続してタップしても、重複して再生されない。(前回の効果音を途中でキャンセルして、再び最初から流し始めるイメージ)
(e.g. 1秒で3回タップしても、3回とも効果音が再生される)

環境(2024/08/17)

以下の環境で検証しました。(これ以前の環境でも同じ現象が起こると思う)

  • Xcode 15.3
  • iOS 18

まとめ

AVAudioPlayerplay() methodを呼ぶことで、Buttonをタップしたときに効果音を流す機能を実装できる。
素直にplay()を呼ぶだけでは、連続でタップしたときに、直前のタップによる効果音が再生中なら、新たにタップしたときの効果音は再生されない。
play()を呼ぶ前に、再生時間を0にセットすることで、連続したタップでも、毎回、効果音を再生できる。(audioPlayer.currentTime = 0)

Refs

Discussion