在MusicSequenceUserCallback中传递的函数参数

时间:2016-08-25 18:25:00

标签: swift type-alias

以下func是Core Audio

中MusicSequence的一部分
func MusicSequenceSetUserCallback(_ inSequence: MusicSequence, _ inCallback: MusicSequenceUserCallback?, _ inClientData: UnsafeMutablePointer<Void>) -> OSStatus

MusicSequenceUserCallback在API中定义为:

typealias MusicSequenceUserCallback = (UnsafeMutablePointer<Void>, MusicSequence, MusicTrack, MusicTimeStamp, UnsafePointer<MusicEventUserData>, MusicTimeStamp, MusicTimeStamp) -> Void

我不清楚如何将自定义函数传递给MusicSequenceSetUserCallback。知道了Swift中的func类型,我使用与MusicSequenceUserCallback完全相同的参数创建了一个自定义函数,并尝试将其设置为:

var argFunc: MusicSequenceUserCallback = myCallback

但我在上面的代码行中收到错误A C function pointer can only be formed from a reference to a 'func' of a literal closure

修改

这是我写的回电话:

func myCallback(inClientData: UnsafeMutablePointer<Void>, sequence: MusicSequence, track: MusicTrack, eventTime: MusicTimeStamp, data: UnsafePointer<MusicEventUserData>, startSliceBeat: MusicTimeStamp, endSliceBeat: MusicTimeStamp) -> Void {
    // do something
}

1 个答案:

答案 0 :(得分:2)

您收到错误是因为回调需要是一个自由函数,或者一个没有任何捕获本地上下文的闭包。实例方法捕获self引用,因此您不能将它们用作回调。

解决方案是:

  • myCallBack声明为全局函数,或
  • myCallback声明为内部函数/闭包,并确保它不会捕获任何局部变量

如果您需要在回调中使用类的实例成员,可以通过inClientData参数将回调从free函数转发到类的实例来实现:

class MyMusicClass {

    func myCoreAudioFunction() {

        .............

        func seqCB(inClientData: UnsafeMutablePointer<Void>, sequence: MusicSequence, track: MusicTrack, eventTime: MusicTimeStamp, data: UnsafePointer<MusicEventUserData>, startSliceBeat: MusicTimeStamp, endSliceBeat: MusicTimeStamp) -> Void {

            // we know for sure we have a MyMusicClass instance here, so the cast should be OK
            // care to be taken though to unregister the callback if the `MyMusicClass` instance gets deallocated, to avoid the zombie
            let client = unsafeBitCast(inClientData, MyMusicClass.self)
            client.musicSeqenceCallback(sequence, track: track, eventTime: eventTime, data: data, startSliceBeat: startSliceBeat, endSliceBeat: endSliceBeat)
        }

        MusicSequenceSetUserCallback(myMusicSequence,seqCB, unsafeBitCast(self, UnsafeMutablePointer<Void>.self))
    }

    func musicSeqenceCallback(sequence: MusicSequence, track: MusicTrack, eventTime: MusicTimeStamp, data: UnsafePointer<MusicEventUserData>, startSliceBeat: MusicTimeStamp, endSliceBeat: MusicTimeStamp) -> Void {
        // do anything you want here, there are no more restrictions :)
    }
}