> On Sep 25, 2017, at 6:12 PM, Kenny Leung via swift-users 
> <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

Reply via email to