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 の型を投げ入れても例外で止まるようなことはないので、型の一致判定に使う分には問題無さそう。
参考