Hi Greg. Thanks for the insight. In this case, I think I’m saved because I don’t actually need to capture self in the block. I guess I was just too far along on my train to realize that. I think this will work and it will keep the code simple and neat.
I guess we'll see as I complete this project whether I really have everything I need for the callback block. I may have to resort to one of the other measures you all have suggested. Thanks again! -Kenny > On Sep 26, 2017, at 12:40 AM, Greg Parker <gpar...@apple.com> wrote: > >> >> On Sep 25, 2017, at 6:12 PM, Kenny Leung via swift-users >> <swift-users@swift.org <mailto:swift-users@swift.org>> wrote: >> >> I’m trying to implement the AudioQueue example from Apple in Swift, and keep >> it as Swifty as I can. I’ve run into a problem where I have a let ivar for >> the AudioQueue, but the only way to initialize that let ivar is to pass a >> block to the function that creates the AudioQueue. I get the error, >> "Variable 'self.mQueue' used before being initialized”. Is there any way to >> get around this catch? > > The compiler cannot guarantee that the code running inside your block does > not try to use mQueue before it is initialized. Swift strictly enforces its > initialization rules, so the compiler rejects your code. > > One common solution is to change mQueue into an implicitly-unwrapped optional > var. The compiler still can't tell if your block object uses mQueue before it > is initialized, but if it does it will get a well-defined runtime error due > to the nil IUO. That well-defined error is sufficient to pacify the > initialization rules. > > Another solution might be to divide your data into two different types. It > looks like the block object only needs to access self.audioBuffers and > self.source. You might be able to box those two fields into a separate class > type and have the block object capture a reference to that object only. Then > the initialization order is simple enough for the compiler to understand: > 1. PDAudioPlayer.init() initializes a source+audioBuffers object. > 2. PDAudioPlayer.init() calls AudioQueueNewOutputWithDispatchQueue(), passing > it a block that captures a reference to the fully-initialized > source+audioBuffers object. > 3. PDAudioPlayer.init() uses the results of #1 and #2 to complete its own > initialization or return nil. > This adds an extra allocation and extra indirection to each PDAudioPlayer > object, but as long as you don't have millions of these things the > performance difference should be negligible. > > >> ———8<————8<———— >> class PDAudioPlayer { >> static let kNumberBuffers :Int = 3 // 1 >> //var mDataFormat:AudioStreamBasicDescription // 2 >> let mQueue :AudioQueueRef // 3 >> //var mBuffers :[AudioQueueBufferRef] // 4 >> //var mAudioFile :AudioFileID? // 5 >> var bufferByteSize :UInt32? // 6 >> var mCurrentPacket :Int64? // 7 >> var mNumPacketsToRead :UInt32? // 8 >> var mPacketDescs :UnsafePointer<AudioStreamPacketDescription>? // 9 >> var mIsRunning: Bool = false // 10 >> >> let dispatchQueue :DispatchQueue >> let source :PDFileAudioSource >> var audioBuffers :[PDAudioBuffer] >> >> init?(source:PDFileAudioSource) { >> self.source = source >> self.dispatchQueue = DispatchQueue(label:"AudioPlayer", >> qos:.default, attributes:[], autoreleaseFrequency:.workItem, target:nil) >> self.audioBuffers = [PDAudioBuffer]() >> >> var tempAudioQueue :AudioQueueRef? >> var dataFormat = source.mDataFormat >> let status = AudioQueueNewOutputWithDispatchQueue(&tempAudioQueue, >> &dataFormat, 0, self.dispatchQueue) { [weak self] (queue, buffer) in // >> ERROR on this line >> guard let this = self else { >> return // block >> } >> guard let audioBuffer = >> this.audioBufferForAudioQueueBuffer(aqBuffer:buffer) else { >> return // block >> } >> this.source.fillBuffer(audioBuffer) >> } >> if status != 0 { >> return nil >> } >> guard let audioQueue = tempAudioQueue else { >> return nil >> } >> self.mQueue = audioQueue >> } >> >> private func >> audioBufferForAudioQueueBuffer(aqBuffer:AudioQueueBufferRef) -> >> PDAudioBuffer? { >> for buffer in self.audioBuffers { >> if buffer.audioQueueBuffer == aqBuffer { >> return buffer >> } >> } >> return nil >> } >> }
_______________________________________________ swift-users mailing list swift-users@swift.org https://lists.swift.org/mailman/listinfo/swift-users