AVAudioSession の outputVolume について addObserver で変更の通知を受け取るような実装を行いました。
swift
1 override func viewWillAppear(_ animated: Bool) { 2 super.viewWillAppear(animated) 3 4 setSystemVoiceObserver() 5 } 6 7 func setSystemVoiceObserver() { 8 let audioSession: AVAudioSession = AVAudioSession.sharedInstance() 9 try! audioSession.setCategory(AVAudioSessionCategoryAmbient) 10 try! audioSession.setActive(true) 11 12 audioSession.addObserver(self, forKeyPath: "outputVolume", options: .new, context: nil) 13 } 14 15 override func viewDidDisappear(_ animated: Bool) { 16 super.viewDidDisappear(animated) 17 18 let audioSession: AVAudioSession = AVAudioSession.sharedInstance() 19 audioSession.removeObserver(self, forKeyPath: "outputVolume", context: nil) 20 }
swift
1 override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) { 2 if keyPath == "outputVolume" { 3 let i: UInt32 = UInt32(change![.newKey]! as! Float * 100) 4 setVolumeLabelText(i) // 音量の変更を受け取ったあとに行う処理 5 } 6 }
上記コードのchangeパラメータの中身を取得するのに強制的アンラップを1行で3回も行ってしまいました。swiftlintにも怒られてしまい、とても罪悪感があるのですが、一方で「受け取るものの型も存在もわかりきってるのだからいいんじゃないか」とも思っています。
(1)このような通知を受け取るメソッドで実行時にエラーになる可能性はどれくらいあるのでしょうか?
(2)このような通知のoptional型をいい感じに取り出す方法はないでしょうか?if letとoptional chainingでいけるか試してみましたが、
swift
1 if let i: UInt32 = UInt32(change?[.newKey]? as? Float * 100) { 2 setVolumeLabelText(i) // 音量の変更を受け取ったあとに行う処理 3 }
上記のコードではas?をas!や(change?[.newKey] as? Float)!で置き換えるようにコンパイラが警告してきて、結局どこかで強制アンラップをしなければならないような状態です。できれば1行でnil合体演算子も使いたくはないのですが……。
回答2件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。