1

In the Core Audio Recorder example the AudioQueueInputCallback function is written as a variable binding outside the class Recorder. I am trying to use it inside a struct, but I am not able to access any instance methods. It gives the error, Instance members cannot be used on type.

struct Recorder {
    private var log = Logger()
    private let utils = Utils()


    func record() {
        // ...
        AudioQueueNewInput(&recordFormat, audioQueueInputCallback, &recorder, nil, nil, 0, &queue)
    }

    private let audioQueueInputCallback: AudioQueueInputCallback = { (inUserData: UnsafeMutableRawPointer?, inQueue: AudioQueueRef,
                                                                  inBuffer: AudioQueueBufferRef, inStartTime: UnsafePointer<AudioTimeStamp>,
                                                                  inNumPackets: UInt32, inPacketDesc: UnsafePointer<AudioStreamPacketDescription>?) in
        log.debug()   //  <-- error: instance member cannot be used on type Recorder

}

How to write audioQueueInputCallback inside a struct such that the instance variables can be accessed inside it?


Update: If I change the var to lazy as:

private lazy var audioQueueInputCallback: AudioQueueInputCallback = {
        (_ inUserData: UnsafeMutableRawPointer?, _ inQueue: AudioQueueRef,
        _ inBuffer: AudioQueueBufferRef, _ inStartTime: UnsafePointer<AudioTimeStamp>,
        _ inNumPackets: UInt32, _ inPacketDesc: UnsafePointer<AudioStreamPacketDescription>?) in
    log.debug("audio queue callback")
}

I am getting Closure cannot implicitly capture a mutating self parameter error.

John Doe
  • 2,225
  • 6
  • 16
  • 44
  • 1
    Possibly helpful: [How to use instance method as callback for function which takes only func or literal closure](https://stackoverflow.com/q/33260808/1187415) – Martin R Mar 04 '19 at 06:11

2 Answers2

5

In Swift, you cannot pass a function to be used as a C callback function if it is declared as a method of a type. It must be a global (top level) or a local (inside another func). That is why the example makes it a global.

matt
  • 515,959
  • 87
  • 875
  • 1,141
  • For an example, see https://github.com/mattneub/Programming-iOS-Book-Examples/blob/master/bk2ch14p640systemSound/ch27p910systemSound/ViewController.swift. I've declared the C callback as a global, but I've also marked with a comment the other place in the code where it could have been declared as a local. – matt Mar 03 '19 at 15:25
0

You can use self inside the closure of a lazy property. So you should define 'audioQueueInputCallback' as lazy.

kaangurses
  • 76
  • 1
  • It gives `Closure cannot implicitly capture a mutating self parameter`. error. I have updated the question to reflect the change. – John Doe Mar 03 '19 at 15:15