CoreAudioの中の、AudioToolboxに取り組んでいます。
システムサウンド自体は1行で鳴らせます。※マナーモードは解除
AudioServicesPlaySystemSound(1108) // シャッター音
鳴らし終えたときに呼ばれるコールバック関数を
AudioServicesAddSystemSoundCompletiondeで登録しようとして、
つまづきました![]()
C言語のように、関数名がその関数へのポインタを表すのは Swiftも同じですが、
ここにはグローバル関数を指定しなければいけませんでした。
private func myCompletionCallback(ssID: SystemSoundID, clientData: UnsafeMutableRawPointer?) { print("didPlay") } class ViewController: UIViewController { ︙ AudioServicesAddSystemSoundCompletion(ssID, nil, nil, myCompletionCallback, nil) AudioServicesPlaySystemSound(ssID)
AudioToolboxはC言語で実装された非同期の処理で、メンバー関数だと
鳴り終えた時のコールバック先が有効だという保証がない、という事ですかね。
Swiftの中だけならARCが効くので、メンバー関数を渡すこともできます。
これに気付くのに1日かかりました![]()
「Swiftではポインタの書き方が違うのかも」と勘違いしてしまったからです。
ちなみにクロージャだとこうです。
AudioServicesAddSystemSoundCompletion(ssID, nil, nil, myCompletionCallback, nil) AudioServicesPlaySystemSound(ssID) } let myCompletionCallback: @convention(c) (SystemSoundID, UnsafeMutableRawPointer?) -> Void = {(ssID, clientData) in print("didPlay") }
クロージャは、渡してしまえばあとはお好きにどうぞという事でしょうか。
AudioServicesAddSystemSoundCompletionの定義には、
@escapingというディレクティブが付いています。
しかし、とんだ回り道をしたおかげで、
Swiftのポインタについて調べるきっかけとなりました。
…とでも思わなければやっていられません![]()
Swiftでは、C言語のポインタ関係のテクニックに、いちいち名前が付いています。
例えば 「void *」は、UnsafeMutableRawPointerというそうです![]()
プロレスの大技みたいですね![]()
![]()
上の例だとさらに、Optional UnsafeMutableRawPointerですか。
疲れます![]()