我尝试使用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。
答案 0 :(得分:5)
大卫的回答是正确的。但只是为了澄清,AudioServicesSystemSoundCompletionProc需要在objective-c中完成,然后桥接到swift。你可以自己编写一个实现,或者......它已经在你身上完成了:https://gist.github.com/jparishy/7b76edf8d0fcca1d63b0(正如David所说)
您需要转到该链接,下载文件FunctionPointer.h和FunctionPointer.c,将其放在项目文件夹中,然后使用桥接头将其链接到swift。
要做到这一点:
现在您可以在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)
可以在此处看到答案:https://gist.github.com/jparishy/7b76edf8d0fcca1d63b0
Julius Parishy的解决方案(https://stackoverflow.com/users/1164263/julius-parishy)
答案 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)