如何在Swift中实现AudioServicesSystemSoundCompletionProc?

时间:2014-11-08 23:53:26

标签: c xcode swift

我尝试使用Xcode中的Swift为AudioServicesAddSystemSoundCompletion中的参数创建AudioServicesSystemSoundCompletionProc实例。

这是我到目前为止所做的事情

func completionCallback(ssID:SystemSoundID,clientData:UnsafeMutablePointer<Void>) -> Void {

}

var foo:(ssID:SystemSoundID,clientData:UnsafeMutablePointer<Void>) -> Void = completionCallback;

AudioServicesAddSystemSoundCompletion(soundID, nil, nil, foo, nil);

我在一些指南的帮助下写了这篇文章,解释了如何在Swift中编写等效的C函数指针,但这会引发这个错误:

'(ssID: SystemSoundID, clientData: UnsafeMutablePointer<Void>) -> Void' is not convertible to 'AudioServicesSystemSoundCompletionProc'

文档显示了Objective-C声明:

typedef void (*AudioServicesSystemSoundCompletionProc) ( SystemSoundID ssID, void *clientData );

这是使用Xcode时显示的声明:

typealias AudioServicesSystemSoundCompletionProc = CFunctionPointer<((SystemSoundID, UnsafeMutablePointer<Void>) -> Void)>

我不确定如何在Swift中正确实现AudioServicesSystemSoundCompletionProc。

5 个答案:

答案 0 :(得分:5)

大卫的回答是正确的。但只是为了澄清,AudioServicesSystemSoundCompletionProc需要在objective-c中完成,然后桥接到swift。你可以自己编写一个实现,或者......它已经在你身上完成了:https://gist.github.com/jparishy/7b76edf8d0fcca1d63b0(正如David所说)

您需要转到该链接,下载文件FunctionPointer.h和FunctionPointer.c,将其放在项目文件夹中,然后使用桥接头将其链接到swift。

要做到这一点:

  • 转到项目的构建设置,向下滚动到Objective-C Bridging Header所在的位置,将内容编辑到&#34; YourProject / Bridging-Header.h&#34; (其中YourProject是项目的名称)
  • 在项目中创建一个objective-c头文件,并将其命名为Bridging-Header.h
  • 在头文件中添加#import&#34; FunctionPointer.h&#34;

现在您可以在swift项目中的任何位置访问FunctionPointer ... sweet

回到您的代码中的compeletion处理程序,您要使用AudioServicesAddSystemSoundCompletion,执行以下操作:

    // at the top of the class
    var functionPointer: AudioServicesCompletionFunctionPointer?

    // in the code
    var me = self
    let userData = withUnsafePointer(&me) { ptr in
        return unsafeBitCast(ptr, UnsafeMutablePointer<Void>.self)
    }
    self.functionPointer = AudioServicesCompletionFunctionPointer(systemSoundID: soundId, block: {(systemSoundID: SystemSoundID, userData: UnsafeMutablePointer<Void>) -> () in
        // sound has ended, do your stuff here
        }, userData: userData)
    AudioServicesAddSystemSoundCompletion(soundId, CFRunLoopGetMain(), kCFRunLoopDefaultMode, AudioServicesCompletionFunctionPointer.completionHandler(), userData)

你必须将NSObject改为TheClassYou&reungsingThisIn和soundId to your soundId

答案 1 :(得分:5)

你可以把它作为一个闭包,就像Swift 2.0一样。

AudioServicesAddSystemSoundCompletion(soundID, nil, nil, { (soundID, clientData) -> Void in

    // Your completion callback...                            
    AudioServicesDisposeSystemSoundID(soundID)

}, nil) 

进一步info from Apple(向下滚动到功能指针):

  

C函数指针作为闭包导入Swift

答案 2 :(得分:2)

答案 3 :(得分:2)

let myData = unsafeBitCast(self, UnsafeMutablePointer<Void>.self)
AudioServicesAddSystemSoundCompletion(YOUR_SOUND_ID, CFRunLoopGetMain(), kCFRunLoopDefaultMode,{ (mSound, mVoid) in
        let me = unsafeBitCast(mVoid, YOURCURRENTCLASS.self)
        //me it is your current object so if yo have a variable like
        // var someVar you can do
        print(me.someVar)
    }, myData)

答案 4 :(得分:0)

这适用于Swift 3:

        let weakSelf = UnsafeMutableRawPointer(Unmanaged.passUnretained(self).toOpaque())
        let error = AudioServicesAddSystemSoundCompletion(soundId,
                                                          nil,
                                                          nil,
                                                          {soundId, weakSelfPointer in

                                                            guard let weakSelfPointer = weakSelfPointer else {
                                                                return
                                                            }

                                                            let weakSelfValue = Unmanaged<NAME_OF_SELF_CLASS>.fromOpaque(weakSelfPointer).takeUnretainedValue()

                                                            // Then you can use `weakSelfValue` as you would do with `self`.
                                                            weakSelfValue.A_METHOD_OF_SELF
        }, weakSelf)