Objective-C の API を Swift から使うとき、次のようにオプション項目を Dictionary 型で指定することがよくある。
open class AVPlayerItemVideoOutput : AVPlayerItemOutput {
public init(pixelBufferAttributes: [String : Any]? = nil)
}
普通に Swift 側から API に値を投げる分には何も問題ないのだけど、自分で Any から CoreFoundation 由来の型にキャストする場合にちょっと手間取った。具体的には、↑ の API に渡される [String : Any] の Any を CFAllocator として取り出したい。
普通に as? でキャストすればいいのでは?
🤔
これならわかる:
同じ CoreFoundation 由来の型でも CFString や CFNumber は Swift の String や Int などに as で安全にキャストできるので、特に困ることはない。
let value: Any? = "🤔"
guard let string = value as? String else { return }
let cfString = string as CFString
ただ CFAllocator などは対応する Swift や Objective-C の型がないので、何かしら別の手段で型をきちんと確認してから as! でキャストすることになる。
CFGetTypeID(_:) で型をチェックする
というわけで:
let value: Any? = attributes[kCVPixelBufferMemoryAllocatorKey as String]
let allocator: CFAllocator?
if CFGetTypeID(value as CFTypeRef!) == CFAllocatorGetTypeID() {
allocator = (value as! CFAllocator)
} else {
allocator = nil
}
これで Any から CFAllocator にキャストすることができた。 CFGetTypeID(_:) へは Swift の型を投げ入れても例外で止まるようなことはないので、型の一致判定に使う分には問題無さそう。
参考