Swift 和 AudioFormatGetProperty(_:_:_:_:_:)
Swift and AudioFormatGetProperty(_:_:_:_:_:)
我想知道如何使用 swift.
管理无人管理的 CFType AudioFormatGetProperty()
这个功能是低级的API,还有一些kAudioFormatProperty_XXXreturns
没有注释的 CFType 对象。根据文档,它说
The caller is responsible for releasing the returned string.
The caller must call the CFRelease function for the returned dictionary.
kAudioFormatProperty_FormatName
kAudioFormatProperty_ChannelLayoutName
kAudioFormatProperty_ChannelLayoutSimpleName
kAudioFormatProperty_ChannelName
kAudioFormatProperty_ChannelShortName
kAudioFormatProperty_ID3TagToDictionary
Swift 没有 CFRelease 支持,所以我认为在这种情况下,调用者必须执行类似 CFRelease 的操作。
能给点建议吗?
我的代码片段如下:
var aclSize : Int = 0
let aclPtr : UnsafePointer<AudioChannelLayout>? =
CMAudioFormatDescriptionGetChannelLayout(desc, &aclSize)
var nameSize : UInt32 = 0
let err1 : OSStatus =
AudioFormatGetPropertyInfo(kAudioFormatProperty_ChannelLayoutName,
UInt32(aclSize), aclPtr, &nameSize)
let count : Int = Int(nameSize) / MemoryLayout<CFString>.size
let ptr : UnsafeMutablePointer<CFString> =
UnsafeMutablePointer<CFString>.allocate(capacity: count)
let err2 : OSStatus =
AudioFormatGetProperty(kAudioFormatProperty_ChannelLayoutName,
UInt32(aclSize), aclPtr, &nameSize, ptr)
// do something here
ptr.deallocate() // Is this same as CFRelease(cfstringref)?
我找到了更好的 AudioFormatGetProperty() 解决方案。
简单的解决方法:
kAudioFormatProperty_* 类似于 FormatName 或 ChannelLayoutName return 单个 CFString 值。
在这种情况下,我可以在 ARC 支持下使用以下功能。无需手动释放
//
var formatSize : UInt32 = UInt32(MemoryLayout<CFString>.size)
var format : CFString!
let err : OSStatus =
AudioFormatGetProperty(kAudioFormatProperty_FormatName,
asbdSize, asbdPtr, &formatSize,
&format)
formatString = String(format as NSString)
//
var nameSize : UInt32 = UInt32(MemoryLayout<CFString>.size)
var name : CFString!
let err : OSStatus =
AudioFormatGetProperty(kAudioFormatProperty_ChannelLayoutName,
UInt32(aclSize), aclPtr,
&nameSize, &name)
layoutString = String(name as NSString)
注意:
如何识别"non-annoted CFType object is really unmanaged or not".
以下是我在这个问题上做的廉价调试程序。
我认为这是不好的诀窍,所以我想知道更多更好的方法。
1) 检查 CFType 的 RetainCount。
如果它像 1152921504606846975 这样巨大的价值,那么它是常量 - 不需要 release()。
let ptr : UnsafeMutablePointer<CFString> = ...
CFShow(ptr.pointee) // to confirm it is live
Swift.print(CFGetRetainCount(ptr.pointee)) // to check retainCount
2) 如果它是像 2 或 3 这样的小值,那么尝试像这样自动释放它:
let unmanaged = Unmanaged<CFString>.passUnretained(ptr.pointee)
_ = unmanaged.autorelease()
3) 如果它立即崩溃(在 runloop 内),它会被管理(可能由也可能不由 ARC 管理)
4) 如果它按原样运行,我假设它没有被管理(因此 autorelase 处理 retainCount)
更新:
这是另一个通过 Playground 进行的测试。
以下显示 RetainCount 从 3 更改为 2。
import UIKit
import AVFoundation
let avacl : AVAudioChannelLayout? =
AVAudioChannelLayout(layoutTag: kAudioChannelLayoutTag_AAC_5_1)
var unmanaged : Unmanaged<CFString>? = nil
do {
let aclPtr : UnsafePointer<AudioChannelLayout> = avacl!.layout
var aclSize : Int = MemoryLayout<AudioChannelLayout>.size +
(Int(aclPtr.pointee.mNumberChannelDescriptions) - 1) *
(MemoryLayout<AudioChannelDescription>.size)
var nameSize : UInt32 = UInt32(MemoryLayout<CFString>.size)
let ptr = UnsafeMutablePointer<CFString>.allocate(capacity: 1)
defer { ptr.deallocate() }
_ = AudioFormatGetProperty(kAudioFormatProperty_ChannelLayoutName,
UInt32(aclSize), aclPtr, &nameSize, ptr)
_ = ptr.move() // make CFString managed
unmanaged = Unmanaged<CFString>.passUnretained(ptr.pointee)
CFGetRetainCount(unmanaged?.takeUnretainedValue())
}
CFGetRetainCount(unmanaged?.takeUnretainedValue())
以下显示 RetainCount 从 4 更改为 2。(超出范围时减少 2)
import UIKit
import AVFoundation
let avacl : AVAudioChannelLayout? =
AVAudioChannelLayout(layoutTag: kAudioChannelLayoutTag_AAC_5_1)
var unmanaged : Unmanaged<CFString>? = nil
do {
let aclPtr : UnsafePointer<AudioChannelLayout> = avacl!.layout
var aclSize : Int = MemoryLayout<AudioChannelLayout>.size +
(Int(aclPtr.pointee.mNumberChannelDescriptions) - 1) *
(MemoryLayout<AudioChannelDescription>.size)
var nameSize : UInt32 = UInt32(MemoryLayout<CFString>.size)
var name : CFString!
_ = AudioFormatGetProperty(kAudioFormatProperty_ChannelLayoutName,
UInt32(aclSize), aclPtr, &nameSize, &name)
unmanaged = Unmanaged<CFString>.passUnretained(name!)
CFGetRetainCount(unmanaged?.takeUnretainedValue())
}
CFGetRetainCount(unmanaged?.takeUnretainedValue())
我想知道如何使用 swift.
管理无人管理的 CFType AudioFormatGetProperty()这个功能是低级的API,还有一些kAudioFormatProperty_XXXreturns 没有注释的 CFType 对象。根据文档,它说
The caller is responsible for releasing the returned string.
The caller must call the CFRelease function for the returned dictionary.
kAudioFormatProperty_FormatName
kAudioFormatProperty_ChannelLayoutName
kAudioFormatProperty_ChannelLayoutSimpleName
kAudioFormatProperty_ChannelName
kAudioFormatProperty_ChannelShortName
kAudioFormatProperty_ID3TagToDictionary
Swift 没有 CFRelease 支持,所以我认为在这种情况下,调用者必须执行类似 CFRelease 的操作。 能给点建议吗?
我的代码片段如下:
var aclSize : Int = 0
let aclPtr : UnsafePointer<AudioChannelLayout>? =
CMAudioFormatDescriptionGetChannelLayout(desc, &aclSize)
var nameSize : UInt32 = 0
let err1 : OSStatus =
AudioFormatGetPropertyInfo(kAudioFormatProperty_ChannelLayoutName,
UInt32(aclSize), aclPtr, &nameSize)
let count : Int = Int(nameSize) / MemoryLayout<CFString>.size
let ptr : UnsafeMutablePointer<CFString> =
UnsafeMutablePointer<CFString>.allocate(capacity: count)
let err2 : OSStatus =
AudioFormatGetProperty(kAudioFormatProperty_ChannelLayoutName,
UInt32(aclSize), aclPtr, &nameSize, ptr)
// do something here
ptr.deallocate() // Is this same as CFRelease(cfstringref)?
我找到了更好的 AudioFormatGetProperty() 解决方案。
简单的解决方法:
kAudioFormatProperty_* 类似于 FormatName 或 ChannelLayoutName return 单个 CFString 值。
在这种情况下,我可以在 ARC 支持下使用以下功能。无需手动释放
//
var formatSize : UInt32 = UInt32(MemoryLayout<CFString>.size)
var format : CFString!
let err : OSStatus =
AudioFormatGetProperty(kAudioFormatProperty_FormatName,
asbdSize, asbdPtr, &formatSize,
&format)
formatString = String(format as NSString)
//
var nameSize : UInt32 = UInt32(MemoryLayout<CFString>.size)
var name : CFString!
let err : OSStatus =
AudioFormatGetProperty(kAudioFormatProperty_ChannelLayoutName,
UInt32(aclSize), aclPtr,
&nameSize, &name)
layoutString = String(name as NSString)
注意:
如何识别"non-annoted CFType object is really unmanaged or not".
以下是我在这个问题上做的廉价调试程序。 我认为这是不好的诀窍,所以我想知道更多更好的方法。
1) 检查 CFType 的 RetainCount。
如果它像 1152921504606846975 这样巨大的价值,那么它是常量 - 不需要 release()。
let ptr : UnsafeMutablePointer<CFString> = ...
CFShow(ptr.pointee) // to confirm it is live
Swift.print(CFGetRetainCount(ptr.pointee)) // to check retainCount
2) 如果它是像 2 或 3 这样的小值,那么尝试像这样自动释放它:
let unmanaged = Unmanaged<CFString>.passUnretained(ptr.pointee)
_ = unmanaged.autorelease()
3) 如果它立即崩溃(在 runloop 内),它会被管理(可能由也可能不由 ARC 管理)
4) 如果它按原样运行,我假设它没有被管理(因此 autorelase 处理 retainCount)
更新:
这是另一个通过 Playground 进行的测试。
以下显示 RetainCount 从 3 更改为 2。
import UIKit
import AVFoundation
let avacl : AVAudioChannelLayout? =
AVAudioChannelLayout(layoutTag: kAudioChannelLayoutTag_AAC_5_1)
var unmanaged : Unmanaged<CFString>? = nil
do {
let aclPtr : UnsafePointer<AudioChannelLayout> = avacl!.layout
var aclSize : Int = MemoryLayout<AudioChannelLayout>.size +
(Int(aclPtr.pointee.mNumberChannelDescriptions) - 1) *
(MemoryLayout<AudioChannelDescription>.size)
var nameSize : UInt32 = UInt32(MemoryLayout<CFString>.size)
let ptr = UnsafeMutablePointer<CFString>.allocate(capacity: 1)
defer { ptr.deallocate() }
_ = AudioFormatGetProperty(kAudioFormatProperty_ChannelLayoutName,
UInt32(aclSize), aclPtr, &nameSize, ptr)
_ = ptr.move() // make CFString managed
unmanaged = Unmanaged<CFString>.passUnretained(ptr.pointee)
CFGetRetainCount(unmanaged?.takeUnretainedValue())
}
CFGetRetainCount(unmanaged?.takeUnretainedValue())
以下显示 RetainCount 从 4 更改为 2。(超出范围时减少 2)
import UIKit
import AVFoundation
let avacl : AVAudioChannelLayout? =
AVAudioChannelLayout(layoutTag: kAudioChannelLayoutTag_AAC_5_1)
var unmanaged : Unmanaged<CFString>? = nil
do {
let aclPtr : UnsafePointer<AudioChannelLayout> = avacl!.layout
var aclSize : Int = MemoryLayout<AudioChannelLayout>.size +
(Int(aclPtr.pointee.mNumberChannelDescriptions) - 1) *
(MemoryLayout<AudioChannelDescription>.size)
var nameSize : UInt32 = UInt32(MemoryLayout<CFString>.size)
var name : CFString!
_ = AudioFormatGetProperty(kAudioFormatProperty_ChannelLayoutName,
UInt32(aclSize), aclPtr, &nameSize, &name)
unmanaged = Unmanaged<CFString>.passUnretained(name!)
CFGetRetainCount(unmanaged?.takeUnretainedValue())
}
CFGetRetainCount(unmanaged?.takeUnretainedValue())