Swift vs Objective C指针操作问题

Dee*_*rma 5 objective-c core-audio ios swift swift4

我在Objective C中有这个代码可以正常工作:

list = controller->audioBufferList;
list->mBuffers[0].mDataByteSize = inNumberFrames*kSampleWordSize;
list->mBuffers[1].mDataByteSize = inNumberFrames*kSampleWordSize;
Run Code Online (Sandbox Code Playgroud)

它工作得很棒,它更新了mBuffers [0]和mBuffers [1]的mDataByteSize字段.我尝试在Swift中翻译它但它不起作用:

public var audioBufferList:UnsafeMutableAudioBufferListPointer
Run Code Online (Sandbox Code Playgroud)

在功能上,

let listPtr = controller.audioBufferList.unsafeMutablePointer

let buffers = UnsafeBufferPointer<AudioBuffer>(start: &listPtr.pointee.mBuffers, count: Int(listPtr.pointee.mNumberBuffers))

for var buf in buffers {
    buf.mDataByteSize = inNumberFrames * UInt32(sampleWordSize)
    NSLog("Data byte size \(buf.mDataByteSize)")
}

for buf in buffers {
    NSLog("Data byte size \(buf.mDataByteSize)")
}
Run Code Online (Sandbox Code Playgroud)

mDataByteSize未更新.NSLog在第二次读回环时指向原始值,而不是更新的值.似乎var buf通过制作副本来指代另一个buf.我如何解决它?这是一个纯粹的Swift语言问题,我无法理解.

编辑:正如马丁所指出的那样,我通过修改for循环修复了这个问题

 for i in 0..<Int(listPtr.pointee.mNumberBuffers) {
    buffers[i].mDataByteSize = inNumberFrames * UInt32(sampleWordSize)
}
Run Code Online (Sandbox Code Playgroud)

现在它有效.但这进一步激起了我对Swift语言的好奇心,它是多么直观,对使用指针操纵东西的开发人员来说是多么恼人.为什么以下循环失败?var缓冲区是否按值复制?

     for buf in buffers {
         var buffer = buf
         buffer.mDataByteSize = inNumberFrames * UInt32(sampleWordSize)
     }
Run Code Online (Sandbox Code Playgroud)

要么

    for var buf in buffers {
        buf.mDataByteSize = inNumberFrames * UInt32(sampleWordSize)
    }
Run Code Online (Sandbox Code Playgroud)

编辑2:Hamish的回答引起了对在任何地方使用listPtr的有效性的怀疑.我在一些调用中使用listPtr,例如:

let status = AudioUnitRender(controller.audioUnit!, ioActionFlags, inTimeStamp, inBusNumber, inNumberFrames, listPtr)
Run Code Online (Sandbox Code Playgroud)

我现在需要知道我们在哪里可以使用listPtr以及我们不能使用的地方!

Ham*_*ish 4

对于通话:

let buffers = UnsafeBufferPointer<AudioBuffer>(start: &listPtr.pointee.mBuffers, count: Int(listPtr.pointee.mNumberBuffers))
Run Code Online (Sandbox Code Playgroud)

&listPtr.pointee.mBuffers生成一个临时指针,仅在调用 的初始化程序期间有效UnsafeBufferPointer。因此,尝试使用缓冲区指针会导致未定义的行为(编译器有望在 Swift 5.1 中对此类情况发出警告)。

相反,您可以直接迭代UnsafeMutableAudioBufferListPointer,因为它符合MutableCollection.

例如:

for index in audioBufferList.indices {
  audioBufferList[index].mDataByteSize = inNumberFrames * UInt32(sampleWordSize)
  print("Data byte size \(audioBufferList[index].mDataByteSize)")
}

for buffer in audioBufferList {
  print("Data byte size \(buffer.mDataByteSize)")
}
Run Code Online (Sandbox Code Playgroud)