Swiftでミュート機能をつけます。シンプルにアプリ内のUIから音量のON/OFFのみという機能を目指します。
環境は下記。ターゲットは一応 iOS 9.2 です。
- MacOS 10.11.3(El Capitan)
- Xcode 7.2.1
- Swift 2.1
結論、MPVolumeViewから音量スライダーを取ってくるようにしてみました。
色々調べつつやってみたので、過程も含めておさらい。
UIの作成
UIはボタンのイメージ。
class SampleViewController: UIViewController {
@IBOutlet weak var btnSound: UIButton!
// storyboardで「TouchUpInside」からバインド
@IBAction func pushSound(sender :AnyObject) {
btnSound.selected = !btnSound.selected
changeSound()
}
func changeSound() {
// ミュート(音量のON/OFF)処理
}
}
ミュート機能をつける
UIは良いとしても、探してみればミュート設定にピンポイントなAPIとかライブラリがない。
公式から辿ればまず出てくるのがAVAudioSession。
でもこれは読んでみると、「複数のバックグラウンドアプリと起動中のアプリの相互音声設定」が焦点にされている印象だった。
アプリ設計思想上そこまで考慮はすべきなのかもしれないけど、今回やりたいのはもっとシンプルにアプリ内完結でよい。ってことで次に出てきた候補がMPVolumeViewを使う方法。
なんだけどコーディングがわからん。
良い記事。わかりやすかった。でもObjective-CなのでSwiftに翻訳。
やってみた
先ほどのコードに追加です。
import AVFoundation
import MediaPlayer
class SampleViewController: UIViewController {
// 参照保持用にスライダーを宣言。
var volumeSlider: UISlider!
override func viewDidLoad() {
super.viewDidLoad()
// 音量調整のため、システム音量設定画面をaddview
self.view.backgroundColor = UIColor.clearColor()
let mpVolumeView = MPVolumeView(frame: self.view.bounds)
mpVolumeView.hidden = true;
self.view.addSubview(mpVolumeView)
// 音量調整用のスライダーを取得
for childView in mpVolumeView.subviews {
// UISliderクラスで探索
if (childView.isKindOfClass(UISlider)){
self.volumeSlider = childView as! UISlider
}
}
}
// ミュート(音量のON/OFF)処理
func changeSound() {
if(btnSound.selected){
self.volumeSlider.setValue(1.0, animated: false)
btnSound.setImage(UIImage(named: "btnSoundOn"), forState: UIControlState.Normal)
} else {
self.volumeSlider.setValue(0.0, animated: false)
btnSound.setImage(UIImage(named: "btnSoundOff"), forState: UIControlState.Normal)
}
}
}
- MPVolumeViewでシステム音量画面を取ってくる。
- その中のスライダーから音量を取ってくる。
- スライダーは参照保存しておいて、UIイベントから操作できるようにしておく。
- UIイベントからは保存したスライダーの音量の変更をする。
調整する音量の値はONで1.0(音量最大)とかだと不親切すぎるので、そこは前回値適用などに調整する。
補足
スライダー取得をちゃんと(?)やるならこうかな。
正直リテラルあまり使いたくないし、ループで回すのも気持ち悪いんだけど。
// 音量調整用のスライダーを取得
for childView in mpVolumeView.subviews {
// MPVolumeSliderクラスで探索
if (NSStringFromClass((childView as NSObject).dynamicType).isEqual("MPVolumeSlider")) {
self.volumeSlider = childView as! UISlider
}
}
参考サイト
-
AVAudioSession細かいことまとめ(late 2014)
→AVAudioSession使わなかったけど、わかりやすくて勉強になる記事です。