Xcodeで余計なCleanを避けるスクリプト

 XCodeでフォルダ内のファイルを全てプロジェクトに追加する方法には、二種類あります。

f:id:cflat-inc:20140623093944p:plain

 一つは「Create groups for any added folders」、もう一つは「Create folder references for any added folders」です。フォルダの色が黄色か青色か、という区別の仕方もアリ。

f:id:cflat-inc:20140623093921p:plain

 この二つの違いは以下の通りです:

  • Create groups ...(黄色)
    指定したフォルダと同様にグループ階層を作成し、その中に個別のファイルを追加します。
    フォルダ内に新たにファイルを追加しても、プロジェクトには一切影響がありません。
    リソースにこの方法でファイルを追加した場合、使用時にはフォルダ名を含まずファイル名のみで指定します。
  • Create folder references ...(青色)
    指定したフォルダそのものをプロジェクトに追加します。
    フォルダ内容が変更された場合、自動でXCode上にその変更が反映されます。
    リソースにこの方法でファイルを追加した場合、使用時にはフォルダ名を含んだファイル名で指定します。

 ですので、例えば「これから画像が増えて行くけれど、画像が出来る度にプロジェクトに登録してやるのは面倒くさいぞ」という場合には、「Create folder references ...」の方を選べばOKです。

……と思いきや

 ですが実は、ここに一つ落とし穴があるのでした。

 XCodeでは当然ながら、ビルド時に変更のないファイルをチェックし、不要なコンパイルを抑制する処理を行なっています。しかし、「Create folder references ...」で作った青フォルダの中のファイルを更新した場合、フォルダそのものには全く変更が加わっていないことに注意です。  つまり……ファイルをいくら更新しても、リソースが更新されません。  この状況で正しくリソースの変更を反映するためには、ビルド済みのモジュールから、該当のリソースを削除してやる必要があります。

 一番簡単なのは、一度Product > Cleanとする方法です……が、これでは折角のオブジェクトファイルまで削除してしまうため、巨大なプロジェクトでは再ビルドに恐ろしく時間がかかってしまいます。リソースだけを差し替えるためにソースを全てコンパイルし直すというのは、控えめに言っても愚かの一言です。

 そんなわけで、次のようなスクリプト、rmapp.shを作ってみました:

#!/bin/bash

if [ $# -ne 1 ]; then
  echo "Usage: ./$0 projectname"
  exit 1
fi

for path in ~/Library/Developer/Xcode/DerivedData/$1-*/Build/Products/*
do
  if test -e "${path}/$1.app" ; then
    echo "rm -rf \"${path}/$1.app\""
    rm -rf "${path}/$1.app"
  fi
done

exit 0

 使い方は、次の通りです:

./rmapp TestProject

 やっている事としては、関連するっぽいappを兎に角片っ端から探して削除しているだけです。  同名の別プロジェクトがあればそちらも削除してしまいますが、Cleanするのと比べればappの作成処理にかかる時間など微々たるものなので、気にする必要はないでしょう。