Xcode 6.3.2 で Plugin を動くようにするまで

By | 2015年5月21日

TL;DR

  • Xcode 6.3.2 用の DVTPlugInCompatibilityUUIDs を追加する
  • Xcode 起動時に Plugin を有効にするポップアップがでるようになった
  • 大抵の Plugin はメニューに表示されないが動作は初期設定の動作はする(設定で有効にしないと動かないようなものはダメ)

以下、それぞれの詳細です

DVTPlugInCompatibilityUUIDs を追加

以下のコマンドで一括して DVTPlugInCompatibilityUUIDs(E969541F-E6F9-4D25-8158-72DC3545A6C6) を追加

$ find ~/Library/Application\ Support/Developer/Shared/Xcode/Plug-ins -name Info.plist | xargs -IFILE defaults write FILE DVTPlugInCompatibilityUUIDs -array-add E969541F-E6F9-4D25-8158-72DC3545A6C6

DVTPlugInCompatibilityUUIDs が異なる

普段 defaults read ...DVTPlugInCompatibilityUUIDs を確認してたので無駄にはまった。。。なんで違うのかはよくわかりません。僕の環境だけかもしれませんが defaults read ... は信じないと心に誓いました。

$ defaults read FILE DVTPlugInCompatibilityUUIDs /Applications/Xcode.app/Contents/Info.plist
 
(
    "9F75337B-21B4-4ADC-B558-F9CADF7073A7"
)
$ cp /Applications/Xcode.app/Contents/Info.plist ~
$ plutil -convert xml1 ~/Info.plist
$ cat ~/Info.plist
 
...
  <key>DVTPlugInCompatibilityUUID</key>
  <string>E969541F-E6F9-4D25-8158-72DC3545A6C6</string>
...

Xcode 起動時に Plugin を有効にするポップアップがでるようになった

Plugin の数によって多少メッセージが異なりますが大体こんな感じです

これが曲者で、UUID 追加後に Xcode を起動すると初回のみ表示されます。
"Skip Bundle" を選択すると Plugin が無効になり、Xcode を再起動してもポップアップはでてきません
しかも default が "Skip Bundle" のため、適当に Enter を押すと Plugin が無効になるという悲しさ…

ポップアップを表示する方法

  1. Xcode を閉じる
  2. ~/Application Support/Developer/Shared/Xcode/Plug-ins の名前を変更する
  3. Xcode を再起動
  4. ~/Application Support/Developer/Shared/Xcode/Plug-ins に名前を戻す
  5. Xcode を再起動

こうすれポップアップが表示されるので "Load Bundle" を選択しましょう

メニューを表示する方法

これは Xcode Plugin 開発者用ですね。

どうやら pluginDidLoad: が呼ばれたタイミングだと -[[NSApp mainMenu] itemWithTitle:]nil を返すようになったのが原因です。

NSMenuDidChangeItemNotification を Observe するようにしてメニューを設定するようにすれば出るようになります。
Tuna の場合はこんな感じで対応しました。

PR おくれば大抵マージされると思うので空前の GitHub Chance がやってきたわけですね。
みなさんガンガンおくりましょう。

感想

ただただつらい…

ideplugin を使えるようにするまで

By | 2015年5月4日

最近は Tuna をもっぱら作っているのですが、DebggerUI.ideplugin を使いたくて少し試行錯誤したのでメモを残しておこうかなと思います。

そもそも ideplugin とはなんなのか

Xcode の Plugin として、この形式で提供されています。
/Applications/Xcode.app/Contents/PlugIns 以下にあります。

組み込み方

最初は framework みたいに project に追加すれば使えるようになると思ったのですが違うみたいです。
そうすると以下みたいなエラーがでます。

Undefined symbols for architecture x8664:
"
OBJCCLASS$IDEBreakpointEditorPopoverViewController", referenced from:
objc-class-ref in Tuna.o
ld: symbol(s) not found for architecture x86
64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

シンボルがみつからないようですね。

しばらくググると、「Question about linking a framework(ideplugin)」にいきつきました。
これを見る限り、どうやらこのままだと Resource のコピーしか行われないです。

DebuggerUI.ideplugin の場合ですと

  1. /Applications/Xcode.app/Contents/PlugIns/DebuggerUI.ideplugin を project に追加 (Resource のコピー)
  2. /Applications/Xcode.app/Contents/PlugIns/DebuggerUI.ideplugin/Contents/MacOS/DebuggerU を project に追加 (これ重要!)

これでめでたく使えるようになりましたとさ。

余談

使い方はバイナリからヘッダーを出力する class-dump というコマンドを使います。
これでヘッダーを出力して後はヘッダーから使い方を推測して、トライアンドエラーを繰り返します。

class-dump /Applications/Xcode.app/Contents/PlugIns/DebuggerUI.ideplugin

class-dump でヘッダーを出力しているからあれなんですが、型が id だらけなので本当につらいですね。
これをやっていると、はやく型がある世界にもどっていきたい衝動にかられます。

あと、メジャーなクラスだと github で検索すれば使い方がわかるんでいいんですけど
Breakpoint 関連のクラスは全くないのがとても悲しいです。

とはいえ Tuna 自体、着々とバージョンアップしていっているのでよければ使って頂ければと。

ではでは。

Tuna v0.9.1 リリースしました

By | 2015年3月28日

Tuna を使っていて少し不便なことがあったので更新しましたので、そのアナウンスです。

Tuna について少し説明すると、Aciton 付き Breakpoint を簡単に設定できる Plugin です。
Action 付き Breakpoint はすごい便利なんですけど、いかんせん設定がめんどくさすぎて気軽に使おうと思うようなものではありませんでした。

第18回yidevで「まだNSLogで消耗しているの?」を発表してきました 」が参考になるかなと思います。

v0.9.1 で追加された機能

今後、更新情報があれば Changes をアップデートしていこうと思います。
Alcatraz でインストールしている人は、一旦削除してから再インストールしてください。
自分でインストールしている人は pull して再度ビルドしてもらえれば最新版になります。

menu の位置を変更

Edit から Debug に変更しました。

Generally, Edit menu has menus for editing a TEXT itself.
Tuna's menu is used to put Breakpoints to source code.

In Xcode, menu items which use to control breakpoints are gathered in the Debug menu.
Because, I think that it might better to move Tuna menu into 'Debug' menu.

Toggle Breakpoint(Breakpoint の有効/無効を切り替える)

Breakpoint のアイコンをタップして有効/無効を切り替えることはできるんですけど、ショートカットとしては提供されていません。
わざわざマウスに持ち替えるのめんどくさいですよね?
というわけで Tuna でサポートしました。
デフォルトのショートカットとして Command + Shift + [ を設定しています。

Clear All File Breakpoint(Breakpoint を一括で削除)

Shared, Symbolic Breakpoint などは削除せずに、ファイルに紐付いている Breakpoint のみを一括で削除します。
Tuna を利用してデバッグしていると、至る所に Breakpoint の残骸だらけになってしまいます。
選択して削除するのもめんどくさいですし、
デフォルトのショートカットとして Command + Shift + ] を設定しています。

今後

ユーザーが独自で Action 付き Breakpoint を定義できるようにし、その設定を外部ファイルで管理するようにしようと思っています。

import, export もつけるつもりですけど、設定ファイルの保存場所を自由に設定できるようにしておこうかなと。
保存場所を Dropnbox にしておけば簡単に自分の設定を全ての端末で共有できるので便利ですよね。

それができれば public beta を取り除こうかなと思います。

何が要望などあれば気軽にコンタクトください。ではでは。

第18回yidevで「まだNSLogで消耗しているの?」を発表してきました

By | 2015年3月7日


yidev#18

ちょっと煽り系のタイトルにしてあれでしたが、Xcode の Plugin を作っているよという内容です。
発表して作るモチベーションががあがったので、頑張ろうかなと思います。


みれないかた

反響が良かったのでとりあえず Xcode がクラッシュしない状態にして public beta でリリースしようかなと思います。

Xcode Plugin は難しいので、誰か相談にのってくださいw

運営の方々おつかれさまでした。

爆速でプリントデバッグするCryingを作ったよ -裏-

By | 2014年12月19日

どういうフローで行き着いたかを聞かれることがあったので、iOS アドベントカレンダー19日目-裏-ということでまとめてみました。

本エントリー
爆速でプリントデバッグするライブラリを作ったよ

Swift 熱があがった

この発表を聞き質問して、なんとなく理解が深まった気がして何かできるのではないかと錯覚を起こしたのがきっかけ。

動機

本エントリーより

println から debugPrintln に書き換えたり、メソッドチェーンの途中で println を挟むのってめんどくさくないですか?

思考フロー

ruby の tapp を知っていたので、それっぽいことをどうやって Swfit で実現すればいいんだろうと思いながら、Array 等から定義へジャンプすると Swift の基本となる関数等の定義が書かれているファイルがあるので、それを読んでなんかいけそうな class とかあったりしないかなと調べ始めました。

AnyObject を拡張すれば…

コンパイルエラーで怒られてしまいます。
Optional と NSObject の拡張はできたけど、Swift のインスタンスだと使えないとか…

Protocol を拡張すれば…

Protocol を拡張したところで、実装がないから無意味。
そもそも Swift で Protocol を拡張できるかどうかは知らない。

全てのクラスを拡張すれば…

これは気合いでどうにかするパターン。
Swift で定義されてるだけならまだどうにか…なる…か…
Swift で書かれたライブラリで定義されてるインスタンスには使えないので、そんなの全てに対応するとか無理。

つまるところ基底クラスのない世界にうちひしがれた

暗礁に乗り上げ NSHipster を徘徊する

というわけで絶望にうちひしがれながら、なんか他の機能でどうにかできないかなと徘徊してると 「Swift Operators 」にいきつきました。

これを見てる時に、一つの疑問がわきました。

prefix や suffix に演算子をつけた状態でもメソッド呼び出しができるのか?

var i:Int = 0
i++.description;

これがきっかけで、演算子として tapp 的なものを新しく定義してやれば実現できるということにいきつきました。

実装

たいしたことしていないのでソースコードをみてください。

TODO

スタックトレースの結果がきたない

[2014-12-19 05:08:45 +0900] hoge
    at _TFFC11CryingTests25CryingCallPoftfixTestCase20testCallPostfixValueFS0_FT_T_u_KT_GSqPSs9AnyObject__ L:89

NSThread.callStackSymbols() を使って表示するようにしてるんですけど、これがとても見にくい。
(lldb) backtrace だとファイル名と行数がとれてるんだけど、これをどうすれば取れるかがイマイチ分かってない。

せめて addr2line 的なことがしたい。

Building assert() in Swift, Part 2: FILE and LINE」とあるけど、演算子だと引数が決められているのでダメ。

C言語の execinfo.h の backtrace でも結果は変わらない。
おそらく callStackSymbols の内部でも同じものを呼んでるのではないかという推測。

だれか分かる人教えてください。

まとめ

演算子を定義することにより、規定クラスがない世界でも生きていける。
とはいえ演算子を定義したりオーバーロードしたりしすぎると、副作用もあるのでご利用は計画的に。