iOS Advent Calendar 10日目は、いわゆる Bridging-Header の話です。
Swift は素晴らしい言語で積極的に使っていますが、過去の優秀なライブラリは Objective-C で書かれています。
また、 Objective-C はただの C 拡張なので C++ を書くこともできました。
これらのコードを Swift で利用するときはどうしたらいいのでしょうか。
これはなに
- Swift から Objective-C のコードを参照するときは Bridging-Header を使う
- Bridging-Header の作り方を調べた
- 参照先の Objective-C ヘッダから C++ が参照できてはならない
Bridging-Header の作り方
既に Swift を書いているエンジニアなら大抵の方が使用しているとは思いますが、公式サイト のやり方だとイマイチよくわからないということもあります。
自動的に作られない
先ほどの公式サイトには、 Objective-C のファイル(.m)を Swift プロジェクトに入れると以下のようなダイアログが出る と書いてある。
developer.apple.com より引用
しかし、主に CocoaPods を利用する際などプロジェクトに Objective-C ファイルを入れない場合は自動的に作られません。
自分で作る
ならば自分で作ってしまいましょう。
手順は簡単で、
- .hファイルを作る
- Build Settings で設定する
だけです。
.h ファイルを作る
よく検索すると、 ProjectName-Bridging-Header.h という名前にしろ、と書いている記事が多いですがぶっちゃけ名前はなんでもいいです。
今回は Hoge.h という名前で作ってみました。
自動生成のものに名前を合わせて ProjectName-Bridging-Header.h で作るのがいいと思いますが…
Build Settings で設定する
検索窓に "Bridging" くらいまで入れると当該の欄しか出てこないと思います。
そこに Bridging-Header までのパスを書けば終わりです。
プロジェクトルートに置いているならば、
$(SRCROOT)/$(PROJECT)/Hoge.h
でOKです。
あとは Bridging-Header 内で Objective-C のヘッダを #import
して Swift で使っちゃいましょう。
Objective-C++ のコードを Bridge する
Swift は Objective-C のコードを上記の Bridging-Header で呼び出すことができます。
しかし、 C++ には対応していません。ゆえに Objective-C++ を使用する場合は気をつける点があります。
Bridging-Header で import するヘッダから C++ を参照できてはいけない
考えてみれば納得できるのですが、Swift が Bridging-Header を見ているわけで、そこに C++ があってはいけないということですね。これは Objective-C++ であっても同じです。
Bridging-Header に import するヘッダからはなんとかして C++ 成分を除きましょう。
どうしてもだめな場合は
#ifdef __cplusplus
... cpp code...
#endif
として逃げた経験がありますが、本来の意図と異なるのでできればやりたくないですね。
所感
Bridging-Header のおかげで CocoaPods も使えるし過去の遺産を再利用できるのですばらしい仕組みだと思っています。
でもあえて欲を言うなら C が見えるなら C++ も見てほしかった…
というのも C++ のモジュールを Swift で使いたかったので一度 Objective-C++ で C++ モジュールのラッパを書き、参照しようとしたら上記の罠にハマったからです。
もっと Swift エンジニアが増えて全部 Swift でまかなえるようになる日を願って…