みなさんは、補完機能があるIDEと補完機能がないIDE、どちらが好きですか?僕は補完機能があるIDEの方が好きです。でも悲しいことに最近、特定のプロジェクトでXcodeの補完機能が失われるという事象に遭遇してしまいました。
起きていた現象
具体的には上記のように、変数の型に<<error type>>
と表示されてしまい、この<<error type>>
と表示された変数については補完やコードジャンプといったIDEの機能が使えなくなる、という現象です。
このように、 tableView.
と打っても、補完してくれないどころか警告を出してくる。いや、警告を出したいのは俺だ。member name
の候補をお前が早く提示しろ、という気持ちになりますね。型の情報が失われているので、テキストの色も黒ばかりです。
なおこの問題はXcode7.3の頃から発生していて、Xcode8でも同様に発生することを確認しています。
改善のために試したこと
下記のようなことは試してみましたが、効果がありませんでした。
- Cleanする
- Xcodeを再起動する
- Derived Dataを削除する
- 祈りながらSwift3.0対応してみる
正確にはDerived Dataの削除については、一瞬だけ効果があるように見えましたが数分作業すると結局 <<error type>>
が出現します。
解決法
直接的な助けになったのは、Appleのフォーラムの下記の書き込みです。
要約すると
- CococaPodsがビルドディレクトリにヘッダファイルをコピーするのが原因であるようだ
- これにより、SourceKitが正しくコードを解釈できなくなってしまう
- 解決するためには、ビルド後にビルドディレクトリの余計なヘッダファイルを削除すれば良い
具体的には、プロジェクト設定の Build Phases
に下記のようなRun Script
を追加する。
function removeHeaders() {
find $BUILD_ROOT/Debug-iphonesimulator/ -name '*.h' -exec rm -f {} \;
}
removeHeaders
ということが書かれています。最初は半信半疑だったのですが、実際にこのスクリプトを追加してビルドしてみると...
なんと! <<error type>>
が消滅して型がある世界にもどって来ました!IDEではコードに色がつくということも忘れかけていましたが、しっかりと色が付いてます。
なお、上記のスクリプトではシミュレータだけしか対応できないので、 実機の場合にはスクリプトの Debug-iphonesimulator
と記述されている部分を Debug-iphoneos
と変更する必要があります。
自分の場合は、下記のようなスクリプトをビルド時に実行してディレクトリが存在すれば両方消すようにしておきました。
#!/usr/bin/env ruby
def remove_header_files(dir)
return unless File.exists?(dir)
cmd = "find #{dir}"
opt = '-name "*.h" -exec rm -f {} \;'
system("#{cmd} #{opt}")
end
build_dir = ENV['BUILD_ROOT']
exit if build_dir.nil?
simulator_dir = build_dir + "/Debug-iphonesimulator/"
device_dir = build_dir + "/Debug-iphoneos/"
remove_header_files(simulator_dir)
remove_header_files(device_dir)
自動補完もコードジャンプも動作せず、IDEの定義とは...と考えはじめていたのですが、無事直ってよかったです。いやぁ、IDEって最高ですね。