2014-11-08 163 views
4

我想和無法創建AudioServicesSystemSoundCompletionProc的實例在AudioServicesAddSystemSoundCompletion中使用Xcode中的Swift的參數。如何在Swift中實現AudioServicesSystemSoundCompletionProc?

這裏就是我有這麼遠

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

} 

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

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

我寫這與一些導遊介紹如何編寫斯威夫特同樣的C函數指針的幫助,但是,這將引發此錯誤:

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

文檔顯示Objective-C的聲明:

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

這是declar當使用Xcode時顯示:

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

我不確定如何在Swift中正確實現AudioServicesSystemSoundCompletionProc。

+0

任何進展呢?我找不到一個不使用Obj-C代碼的解決方案,包括David的答案。 – Sean 2015-02-01 21:14:35

+0

[使用Swift CFunctionPointer將回調傳遞給CoreMIDI API](http://stackoverflow.com/questions/25514176/using-swift-cfunctionpointer-to-pass-a-callback-to-coremidi-api) – rickster 2015-02-15 17:21:51

回答

5

大衛的答案是正確的。但是爲了澄清,AudioServicesSystemSoundCompletionProc需要在objective-c中完成,然後跨接到swift。您可以自己編寫一個實現,或者...它已經在這裏完成了:https://gist.github.com/jparishy/7b76edf8d0fcca1d63b0(如David提到的)

您需要轉到該鏈接,下載文件FunctionPointer.h和FunctionPointer.c,把它放在你的項目文件夾中,然後使用橋接頭將其鏈接到swift。

爲了做到這一點:

  • 轉到您的項目的構建設置,向下滾動到那裏說的Objective-C橋接報,編輯內容爲「YourProject /橋接-Header.h」(其中YourProject被你的項目名稱)
  • 在項目中創建一個Objective-C頭文件,並將其命名爲橋接,Header.h
  • 頭文件中,添加#進口「FunctionPointer.h」

現在y OU可以隨時隨地訪問您的FunctionPointer SWIFT項目中...甜

回到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'reUsingThisIn並聲音指向您的聲音

+0

肯定會學到一些東西。 +1。謝謝。 – Unheilig 2015-02-15 15:15:59

+0

這是令人鼓舞的,謝謝 – lzl 2015-02-16 21:05:01

5

從Swift 2.0開始,您可以將它作爲閉包使用。

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

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

}, nil)  

而且info from Apple(向下滾動到函數指針):

C function pointers are imported into Swift as closures

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) 
0

這個工作在斯威夫特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)