初めてのXcode 5 プラグイン開発
ヤフー vs クラスメソッド「iOS 炎の7番勝負」でXcode プラグインについて話しました
この記事は、ヤフー vs クラスメソッド「iOS 炎の7番勝負」で話した「Xcodeプラグインで快適な開発ライフを」の補足記事になります。
まえおき
IDEとプラグイン
プラグインって聞くと Eclipse を連想される方が多いかと思います。Eclipse だとそもそも言語用のプラグインやらバージョン管理(git、SVN)やら開発に最低限必要なものがプラグインとして提供されています。なので、Eclipse にとってプラグインはなくてはならない存在と言えます。
Xcodeとプラグイン
Xcode は非常に優秀な IDE で、プラグインを入れなくても iOS 開発に最低限必要なものはほとんど揃っています。なので Xcode では、Eclipse のようにプラグインを入れる必要はありません(決して Eclipse をDisってるわけではありません!)。
じゃあ Xcode にとってプラグインってなんなの?って話になりますが、Xcode にとってのプラグインとはあったらいいのになぁって機能を実現するためのものって位置付けになります。
代表的な Xcode プラグイン
Eclipse ほど数は無いですが、Xcode のプラグインもわりと充実してます。代表的なものとしては以下のものがあります。
<
dl>
詳しくは Xcode の便利プラグインまとめ - Qiita でわかりやすくまとめてありましたので、そちらを見てみてください。
Xcode プラグインって自分で作れるの?
結論から言うと作れます!というわけで前置きが長くなりましたが、この記事ではXcodeプラグインの作り方について解説したいと思います。
必要なもの
Xcode プラグインの開発に必要なものは、
- Mac
- Xcode
のたった2つです。皆さん持ってますよね。
必要なスキル
Xcode プラグインの開発に必要なスキルも2つ。
- Objective-Cの知識
- OS Xアプリ開発の知識
です。
OS Xアプリ開発の知識と書きましたが、ゴリゴリのUIを提供するプラグインでなければそんな大したことないです。
Xcode プラグインで Hello world!
それでは早速初めてのプラグインを作成してみましょう。今回やることは「Xcode 起動時に Hello world!をログに出力する」です!非常にムダすぎるプラグインですがまずは作ってみましょう。
流れはだいたいこんな感じです。
- Xcodeプロジェクトの作成
- Info.plistの設定
- Build settingsの設定
- 実装
- ビルド
- Xcode を再起動
開発環境
今回は以下の環境を前提に話を進めていきたいと思います。
- OS X 10.9
- Xcode 5.0.2
Xcode プロジェクトの作成
Xcode プラグインを開発するにはふつうに Xcode プロジェクトを作成します。 早速 Xcode を開き、新規プロジェクトの作成画面をひらきましょう。
使用するプロジェクトのテンプレートは、OS X > Framework & Library > Bundleです。
プロジェクト名はプラグインの名前になります。ここでは HelloWorldPluginとします。そして、Framework に Cocoa を選択します。あとは任意です。
Info.plistの設定
プロジェクトを作成したら、HelloWorldPlugin-Info.plistを開いて以下の項目を追加します。
キー | 型 | 値 |
---|---|---|
XCGCReady | Boolean | YES |
XCPluginHasUI | Boolean | NO |
XC5Compatible | Boolean | YES |
XC4Compatible | Boolean | YES |
DVTPlugInCompatibilityUUIDs | Array | 37B30044-3B14-46BA-ABAA-F01000C27B63 |
この辺は Xcode プラグイン開発時のお決まりのようです。
DVTPlugInCompatibilityUUIDsの調べ方
DVTPlugInCompatibilityUUIDs は対応する Xcode の UUID を記述するらしいです。Xcode の UUID は、Xcode 5 の Info.plist に記述されています。コンソールで以下のコマンドを実行すれば確認できます。
$ open /Applications/Xcode.app/Contents/Info.plist
Build Settingsの設定
Build Settings で以下の項目の値を変更します。
設定 | 宣言 | 値 | 備考 |
---|---|---|---|
Installation Build Products Location | DSTROOT | $(HOME) | ビルドしたプラグインをインストールする場所。 |
Installation Directory | INSTALL_PATH | /Library/Application Support/Developer/ Shared/Xcode/Plug-ins |
インストールディレクトリ。 絶対パスのように見えますが、そうでないことに注意! 実際は、DSTROOT が先頭に付与されるので、「$(HOME)/Library/Application Support/Developer/Shared/Xcode/Plug-ins」になる。 |
Deployment Location | DEPLOYMENT_LOCATION | YES | DSTROOT で指定した場所ではなく、INSTALL_PATH で指定したディレクトリを使用する。 |
Wrapper Extension | WRAPPER_EXTENSION | xcplugin | ビルドしたプラグインの拡張子。こうすることで、ビルドしてできた成果物に .xcplugin を付与できる。 「$(HOME)/Library/Application Support/Developer/Shared/Xcode/Plug-ins/HelloWorldPlugin.xcplugin」的な。 |
要するに、「ビルドしてできたHelloWorldPlugin.xcpluginを ~/Library/Application Support/Developer/Shared/Xcode/Plug-ins に置きますよ」っていう設定をしています。
これも Xcode プラグイン開発時のお決まりのようです。
実装
プラグインの機能を実装するには、まず プリンシパルクラス(Principal class)というものを作ります。プリンシパルクラスは Xcode 起動時に読み込まれるクラスで、普通のObjective-Cクラスファイルで作成します。 クラス名はプラグイン名が一般的のようです。
いつも通りのファイル作成で OS X > Cocoa > Objective-C class を選択して、HelloWorldPlugin という名前で作成します。
作成したら HelloWorldPlugin.m を開き、以下のように変更します。
HelloWorldPlugin.m
#import "HelloWorldPlugin.h" @implementation HelloWorldPlugin + (void)pluginDidLoad:(NSBundle *)plugin { NSLog(@"Hello world!"); } @end
+ pluginDidLoad: メソッドは Xcode 起動時にプラグインが読み込まれる際に実行されるクラスメソッドです。
今回は「Hello world!」をログに出力するだけですので、このメソッドの中に NSLog() を書いています。
プリンシパルクラスは誰がなるの?
デフォルトでは + pluginDidLoad: メソッドが定義されたクラスがプリンシパルクラスになるようで、クラス名は関係ないみたいです。 また、プリンシパルクラスは Info.plist で明示的に指定できます。
ビルド
これでほとんど完成です。ビルド(Cmd + B)してみましょう。
~/Library/Application Support/Developer/Shared/Xcode/Plug-ins に HelloWorldPlugin.xcplugin があればビルドは成功です。
ls -l ~/Library/Application Support/Developer/Shared/Xcode/Plug-ins
Xcode を再起動(完成!)
あとは、Xcode を再起動すればプラグインが読み込まれます。今回作成したプラグインは「Xcode 起動時に Hello world!をログに出力する」プラグインなので、どっかにログが出力されるはずです。
出力されたログは、/var/log/system.log で確認することができます。一番手っ取り早いのは、コンソールで確認することでしょうか。
すると、/var/log/system.log の中に「Hello world!」が出力されていることが確認できるかと思います。
Xcode プラグイン開発のポイント
ここからは、Xcode プラグイン開発する上でのポイントを解説したいと思います。
開発の流れ
プラグインの開発はだいたいこんな流れになります。
- プラグイン作成
- ビルドしてXcode再起動
- しこんでおいたNSLogを確認
(ログは/var/log/system.logに出力される) - 失敗したらプラグインを消す
(Cleanまたは直接ファイル削除)
機能の呼び出し方
機能の呼び出し方は大きく分けて3つあります。
Xcodeのメニューから
Xcode のメニューにプラグイン用のボタンを追加して、ボタンがタップされたら何中の処理を呼び出します。たぶん、この方法が一番簡単でわかりやすいかと思います。以下の画像は、Lin-Xcode5 のメニューの表示例です。
通知を監視
Xcode では、例えばソースコードを記述したときやファイルを選択したときなど様々なタイミングで通知が発行されます。この通知を監視して、そのタイミングに何らかの処理を実行することが可能です。難点としては、どのタイミングでどの通知が来るか公開されていないことです。。。なので、メニューから実行するより少し難しいです。
既存のメソッドをすりかえ(Swizzling)
Xcode は、莫大なインスタンスの塊です。これらのインスタンスのメソッドが、いろんなタイミングで実行されています。Objective-Cでは、あるインスタンスのメソッドを別のインスタンスのメソッドにすり替えることができます。この仕組みをSwizzlingというらしいです。で、これも通知のときと同様、Xcode にどんなクラスのインスタンスがあるかわかならないため、調べる必要があります。なのでこれも難しいです。
デバッグは NSLog() で
残念ながら、でデバッグは NSLog() で /var/log/system.log にログを出力する以外ありません。。。
プラグインを消したいときは?
自分が作ったプラグインが原因で Xcode が落ちてしまうときや普通に削除したい場合は、Xcode でプラグインプロジェクトを開き、クリーン(Cmd + Shift + K)でOKです。もしくは、~/Library/Application Support/Developer/Shared/Xcode/Plug-ins にあるプラグインを直接削除でもいけます。
学習方法
まず、なんといっても公式ではサポートされていないため、情報が公開されていません。実際に出回っている情報も、英語の場合は Xcode 4 の情報しかなく、日本語はほぼ皆無です。
なので、すでに公開されているプラグインのソースコードを読むことが一番の近道になりそうです。
まとめ
このように、Xcode のプラグインは誰でも作ることができます。便利なプラグインを作って、快適開発ライフをおくりましょう!
次回はもっとつっこんだ話をしたいと思います。