こんにちは。アプリケーション共同開発部の八田です。
Fenrir Advent Calendar 2015 も 14日目となりました。
WWDC 2015 で Swift のオープンソース化が発表され、先日 GitHub で公開されました。私も Linux で動くようになった Swift を少し試してみましたが、動作するプラットフォームが増えて Swift の利用が拡大していくことに期待しています!
さて、Swift で開発しているプロジェクトでどうしても Objective-C のコードを使いたくなった時に、Bridging Header だけでなく Clang の Modules も使えることを最近知ったので、Modules について紹介したいと思います。
Modules とは
Modules は Clang の機能で、ヘッダーファイルで公開された情報をあらかじめバイナリとしてモジュール化しておくというものです。
Modules にはリンクすべきライブラリを自動的にリンクする機能もあり、iOS 7 からは SDK がモジュールとして提供されるようになったことで、UIKit などのフレームワークを import するだけで、リンクの設定はしなくてもよいといった恩恵があります。
Clang の Modules について、詳しくはこちら。
今回は Objective-C のコードをモジュール化して Swift で import する手順を紹介します。
設定
- まず、Xcode のプロジェクトに module.modulemap という名前のファイルを追加します。
- 次に、Build Settings の Swift Compiler – Search Pathes の Import Paths に module.modulemap を含むディレクトリを追加します。
- ここでは、$(SRCROOT) を指定しました。
準備はこれで完了です。
モジュールの宣言
モジュールは module.modulemap で宣言します。 ここでは、記述例を 2つ紹介します。
プロジェクトの構成
ヘッダーファイルを指定
1つ目は個別のヘッダーファイルを指定する方法です。以下のように、”header” に続けてヘッダーファイルのパスを指定します。ここで指定したヘッダーファイルの中で定義されているクラス (MyModel1, MyModel2) が MyModule1 という名前のモジュールにエクスポートされます。
// module.modulemap module MyModule1 { header "Models1/MyModel1.h" header "Models1/MyModel2.h" }
ディレクトリを指定
2つ目はディレクトリを指定する方法です。以下のように、”umbrella” に続けてディレクトリへのパスを指定します。ここで指定した Models2 というディレクトリ配下にある MyModel3.h と MyModel4.h がモジュール化の対象となり、ヘッダーファイルの中で定義されているクラス (MyModel3, MyModel4) が MyModule2 という名前のモジュールにエクスポートされます
// module.modulemap module MyModule2 { umbrella "Models2" export * }
Swift で import
上記のように宣言したモジュールは、同じプロジェクト内で import することで利用できます。
// swift // モジュールを import import MyModule1 import MyModule2 // Objective-C のクラスを利用 let _ = MyModel1() let _ = MyModel3()
最後に
CocoaPods で公開するためのライブラリを書いた時に Swift と Objective-C のコードを混在させたのですが、ライブラリ (Static Library) では Bridging Header が使えなかったので、他の方法を探したところ Modules を使う方法にたどり着きました。
もちろん、iOS アプリケーションのプロジェクトでは、Bridging Header と Modules のどちらも使えますが、ライブラリを開発していて Briging Header が使えなくてお困りの方は試してみてはいかがでしょうか。
フェンリルのオフィシャル Twitter アカウントでは、フェンリルプロダクトの最新情報などをつぶやいています。よろしければフォローしてください!