Я нашел лучшее решение для AudioFormatGetProperty ().
Простое решение:
kAudioFormatProperty_ * подобно FormatName или ChannelLayoutName возвращают одно значение 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)
ПРИМЕЧАНИЕ:
Как определить, действительно ли "необозначенный объект CFType неуправляем или нет".
Ниже приведены дешевые процедуры отладки, которые я делал в этом вопросе.Я считаю, что это плохое ноу-хау, поэтому я хотел бы узнать более лучший способ.
1) Поставьте некоторую проверку для RetainCount CFType.
Если это огромное значение, например 1152921504606846975, то оноявляется константой - не нужно освобождать ().
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)
Обновление:
Это еще один тест на игровой площадке.
После показа 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())