Swift vs Objective C 指针操作问题

Swift vs Objective C pointer manipulation issue

我在 Objective C 中有这段代码,它工作正常:

list = controller->audioBufferList;
list->mBuffers[0].mDataByteSize = inNumberFrames*kSampleWordSize;
list->mBuffers[1].mDataByteSize = inNumberFrames*kSampleWordSize;

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

public var audioBufferList:UnsafeMutableAudioBufferListPointer

在函数中,

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)")
}

mDataByteSize 未更新。在第二个 for 循环中读回的 NSLog 指向原始值,而不是更新的值。似乎 var buf 是通过复制来引用另一个 buf 。我如何解决它?这是一个纯粹的 Swift 语言问题,我无法理解。

编辑:正如 Martin 所指出的,我通过修改 for 循环解决了这个问题

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

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

     for buf in buffers {
         var buffer = buf
         buffer.mDataByteSize = inNumberFrames * UInt32(sampleWordSize)
     }

    for var buf in buffers {
        buf.mDataByteSize = inNumberFrames * UInt32(sampleWordSize)
    }

编辑 2:Hamish 的回答引起了人们对在任何地方使用 listPtr 的有效性的怀疑。我在许多调用中使用了 listPtr,例如:

let status = AudioUnitRender(controller.audioUnit!, ioActionFlags, inTimeStamp, inBusNumber, inNumberFrames, listPtr)

我现在需要知道我们在哪里可以使用 listPtr,哪里不能!

来电:

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

&listPtr.pointee.mBuffers 生成一个临时指针,仅在调用 UnsafeBufferPointer 的初始化程序期间有效。因此,尝试使用缓冲区指针会导致未定义的行为(Swift 5.1 中的编译器will hopefully warn on such cases)。

相反,您可以直接遍历 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)")
}