如何在Swift中实现AudioServicesSystemSoundCompletionProc?

我正在尝试并且未能使用Xcode中的Swift为AudioServicesAddSystemSoundCompletion中的参数创建AudioServicesSystemSoundCompletionProc的实例。

这是我到目前为止所得到的

func completionCallback(ssID:SystemSoundID,clientData:UnsafeMutablePointer) -> Void { } var foo:(ssID:SystemSoundID,clientData:UnsafeMutablePointer) -> Void = completionCallback; AudioServicesAddSystemSoundCompletion(soundID, nil, nil, foo, nil); 

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

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

文档显示了Objective-C声明:

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

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

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

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

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

 AudioServicesAddSystemSoundCompletion(soundID, nil, nil, { (soundID, clientData) -> Void in // Your completion callback... AudioServicesDisposeSystemSoundID(soundID) }, nil) 

Apple的更多信息 (向下滚动到function指针):

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

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

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

要做到这一点:

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

现在,您可以在swift项目中的任何位置访问FunctionPointer …很好

回到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.self) } self.functionPointer = AudioServicesCompletionFunctionPointer(systemSoundID: soundId, block: {(systemSoundID: SystemSoundID, userData: UnsafeMutablePointer) -> () in // sound has ended, do your stuff here }, userData: userData) AudioServicesAddSystemSoundCompletion(soundId, CFRunLoopGetMain(), kCFRunLoopDefaultMode, AudioServicesCompletionFunctionPointer.completionHandler(), userData) 

你必须将NSObject改为TheClassYou’reUsingThisIn和soundId到你的soundId

答案可以在这里看到: https : //gist.github.com/jparishy/7b76edf8d0fcca1d63b0

Julius Parishy的解决方案( https://stackoverflow.com/users/1164263/julius-parishy

 let myData = unsafeBitCast(self, UnsafeMutablePointer.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) 

这适用于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.fromOpaque(weakSelfPointer).takeUnretainedValue() // Then you can use `weakSelfValue` as you would do with `self`. weakSelfValue.A_METHOD_OF_SELF }, weakSelf)