Swift のクロージャーを AnyObject にキャストする
Swift プログラミング
Objective-C との連携を視野に入れた時、Swift のクロージャーを AnyObject にキャストして使いたい場合が出てきます。
それを実現する方法を調べてみました。
Objective-C で設計された API の場合、引数でブロックを受け取るところが Swift からだと AnyObject!
を受け取るように見える場合があります。Swift のクロージャーは AnyObject
ではないため、このままだとクロージャーを API に渡すことができません。
Swift のクロージャーを AnyObject
にキャストするには、次のように、クロージャーの型に
@convention(block)
属性を付けて定義する必要があります。
let closure: @convention(block) (Int, Int) -> String = {
}
このようにすることで、このクロージャーは unsafeBitCast
を使って AnyObject
に変換できるようになる様子です。
let function: AnyObject = unsafeBitCast(closure, AnyObject.self)
あとは、これを Objective-C で作られた API の AnyObject!
のところに渡してあげれば、Objective-C の API に Swift のクロージャーを渡して実行してもらうことが可能になります。
この @convention(block) を指定しないまま unsafeBitCast
で AnyObject
にキャストした場合、実行時に EXC_BAD_INSTRUCTION
例外で強制終了される様子でした。