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.

johndoe
  • 1,721
  • 3
  • 13
  • 33
  • 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
  • 485,702
  • 82
  • 818
  • 1,064
  • 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.

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