目的
XcodeプロジェクトでのSCM(Software Control Management)の利用法を理解する。SCMを使う事で、自身のプロジェクトに対し、アプリケーションをリリースした時の状態、次のバージョン用の状態という風に行程を管理できるようになる。

主要クラス
全般

 このドリルではWindow-based Applicationを使いプロジェクトへの組み込みをおこなっているが、作業自体はすべてのプロジェクトで有効。

 このドリルではXcode 4が必要。
 Xcode 3でもSubversionやCVSによるSCMの利用が可能であるが、ここでは説明しない。

使用テンプレートプロジェクト
Window-based Application

プロジェクトの名称
SCM

事前に体験しておくべきドリル


 SCMはプロジェクトの行程管理に利用する。
 例えばアプリケーションを多人数で作成し、リリース後も機能追加や不具合修正を繰り返す事を考えた場合、プロジェクトは以下のようにいろいろな人間の変更を受けることになる。

$テン*シー*シー-1

 ここで、気の早いBさんがバージョン1.0.0のプロジェクトをコピーし、自宅で機能Bを追加し、これをバージョン1.0.0の元プロジェクトと差し替えたとする。
 しかし、この時、Bさんが元プロジェクトと思っていたものは、すでにAさんによって機能Aが組み込まれたバージョン1.1.0のプロジェクトになっていたとしたら?
 当然、Aさんによる変更はBさんがバージョン1.0.0のプロジェクトをコピーした段階では存在せず、これをAさんによって変更されたバージョン1.1.0のものと差し替えることになるから、機能Aはバージョン1.1.0に追加されないことになる。

$テン*シー*シー-2

 このような事態をさけるためには、AもBもオリジナルプロジェクトのコピーを使い変更をおこない、オリジナルに対しては、その変更部分のみを反映させるようにしなければならない。

$テン*シー*シー-3

 ただ、変更部分反映作業をプログラマ各自が手動でおこなうと非常に負担がかかることになる。
 できれば自分が変更した部分が、自分がコピーを取ったときから、他のプログラマによって変更されていない部分であれば、そのまま変更が反映される方がありがたい。

$テン*シー*シー-4

 また逆に、変更部分が、自分がコピーを取ったときから後に、別のプログラマによって変更されていた場合は、そのまま自動反映はせずに、手動で反映させてくれと注意してもらわなければならない。

$テン*シー*シー-5

 このような調停をやってくれるのがSCMということになる。
 そのためSCMはオリジナルからの変更差分を履歴として管理する機能を持つ。

 変更履歴が管理され、後でどの部分をいつ変更したかを確認できる事は、ひとりで開発している場合でも十分有用であり利用する価値がある。

サンプル実装説明

 まずはWindow-based Applicationプロジェクトを作成する。

 Xcodeを立ち上げ、File>New>New Project…メニューを選びWindow-based Applicationテンプレートを選択する。

$テン*シー*シー-6

 次に出てくる画面ではProduct Name(任意、このドリルではSCMとする)と未入力ならCompany Identifier(任意、このドリルではjp.xcc)を入力。
 Device Familyは任意であるが、このドリルではUniversal、その他の設定も任意であるが、このドリルではすべてOFFとした。

$テン*シー*シー-7

 次に出てくる画面の
Source Control:Create local git repository for this project
が、本課題であるSCMを利用するかどうかの指定となるのでチェックをつける。

$テン*シー*シー-8
プロジェクトの置き場は任意、このドリルではデスクトップとした

 これで、以下のようなプロジェクトウィンドウが開かれる。

$テン*シー*シー-9
プロジェクト項目に「M」バッジがついている事に注目

 Runボタンを押すとプロジェクトがビルドされシミュレータが立ち上がる。

テン*シー*シー-11

テン*シー*シー-12

 シミュレータを終了し、Xcodeに戻り、SCMAppDelegate.mを選択する。

$テン*シー*シー-13

 SCMAppDelegate.mのapplication:didFinishLaunchingWithOptions:メソッドに以下を追加。
- (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
UIView* view = [[UIView alloc]initWithFrame:
CGRectInset(self.window.bounds, 40, 40)];
view.backgroundColor = [UIColor blueColor];
[self.window addSubview:view];


[self.window makeKeyAndVisible];
return YES;
}

 Runさせると以下のようになる。

テン*シー*シー-14

 シミュレータを終了し、Xcodeに戻り、SCMAppDelegate.mの項目を見ると「M」バッジがついている。

テン*シー*シー-15

 これは、このSCMAppDelegate.mがオリジナルから変更された事を表している。
 SCMは正しく機能しているようだ。
 では、この変更をオリジナルに反映させよう。

 File>Source Control…>Commit…メニューを選ぶと、新しいウィンドウが開き、オリジナルからの変更状態が確認できる。

$テン*シー*シー-16

 3種類の表示方法があり、左からプロジェクトウィンドウの左に表示されている形式と同じProject View、実際のファイル構成であるFile View、オリジナルとの違いのあるファイルだけフラットに並べるFlat Viewがある。

テン*シー*シー-17
Project View

テン*シー*シー-18
File View

 チェックが付いていないファイルがいくつか見える。
 例えば.DSStoreファイルなどはFinderが利用しているファイルで、必要になれば新しく作られる。そのためSCM管理に加える必要は無い。

テン*シー*シー-19
Flat View

 左下のテキストエリアに「青色のUIViewを追加した。」としてCommitボタンを押す。これで今回の変更がオリジナルに加えられることになる。

$テン*シー*シー-20

 Commit(委託)した事により現在のプロジェクトとオリジナルは差異が無くなった。「M」バッジも消えている。

$テン*シー*シー-21

 オリジナルへの変更履歴は、File>Source Control…>Repositories…メニューで表示されるOrganizerウィンドウのRepositoriesタグで確認できる。

$テン*シー*シー-22

 SCMAppDelegate.mを選ぶと「青色のUIViewを追加した。」というコメントの履歴があり

$テン*シー*シー-23

 SCMAppDelegate.hにはない。

$テン*シー*シー-24

 このようにCommitした作業は、誰が何の目的でおこなったかを履歴として確認できるようになっている。

 プロジェクト側に戻って、再びSCMAppDelegate.mを変更する。
 次の変更はCALayerを使う関係から、QuartzCoreヘッダーをimportする必要があり、その上で以下のようにapplication:didFinishLaunchingWithOptions:メソッドを拡張する。
#import <QuartzCore/QuartzCore.h>
#import "SCMAppDelegate.h"

@implementation SCMAppDelegate

@synthesize window=_window;

- (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
UIView* view = [[UIView alloc]initWithFrame:
CGRectInset(self.window.bounds, 40, 40)];
view.backgroundColor = [UIColor blueColor];
[self.window addSubview:view];

CALayer* layer = [CALayer layer];
layer.contents = (id)[UIImage imageNamed:@"star.png"].CGImage;
layer.frame = view.layer.bounds;
[view.layer addSublayer:layer];


[self.window makeKeyAndVisible];
return YES;
}

 ここでUIImageに読み込むstar.pngという画像ファイルはPhotoshopで作成し、これをプロジェクトに追加する。
 しかし、以下のようにmaterialというフォルダを作り、その中にstar.pngファイルを置き

$テン*シー*シー-24

 これをドラッグアンドドロップでフォルダごとプロジェクトに追加した場合

$テン*シー*シー-25

 SCMはstar.pngファイルの追加を認識できなかった。
 
$テン*シー*シー-26
ファイルが追加された場合に出る「A」バッジがでない

 star.pngファイル単独をドラッグアンドドロップで登録する場合は問題ないのだが…
 今のところ、対処法としてはターミナルからの直接gitコマンド実行ということになる。
 ターミナルはFinderの移動>ユーティリティメニューで表示されるユーティリティフォルダにある。

$テン*シー*シー-4

 起動するとウインドウが開かれるので、まずはmaterialフォルダに移動する。
cd /Users/自分のユーザー名/Desktop/SCM/SCM/material

 と打ち込む(打ち込むとは上記の文字列を書いて最後にリターンキーまたはエンターキーを押す事を意味する)か、または
cd

 まで書き込んだ状態(cdの後ろにスペースキーで半角スペースを入れておく)でmaterialフォルダをウィンドウにドラッグアンドドロップすれば、materialフォルダへのパスが追加されるようにもなっているので、その後にリターンキーまたはエンターキーを押す。

$テン*シー*シー-28

 materialフォルダに移動したら
git add star.png

 と打ち込む。
 この作業が終わればターミナルを終了し、Xcodeに戻りFile>Source Control>Refresh Statusメニューを選べば以下のようにstar.pngが更新対象として認識される。

$テン*シー*シー-29

 次に、このstar.pngを表示させるためにCALayerを利用するのでQuartzCoreフレームワークをプロジェクトに組み込む。

$テン*シー*シー-30

 プロジェクトアイコンを選び表示される右の画面でTARGETを選び、Build Phasesタグで表示されるLink Binary With Librariesのデスクロージャをクリックすると「+」が現れるので、これをクリック。
 表示されるフレームワークやライブラリの中からQuartzCoreフレームワークを選びAddボタンを押す。

$テン*シー*シー-31

 QuartzCoreフレームワークが追加されたのを確認。

$テン*シー*シー-32

 Runボタンを押すと、いかのように表示される。

$テン*シー*シー-33

 ここまで確認したらシミュレータを終了し、Xcodeに戻る。
 File>Source Control…>Commit…メニューを選び、さきほどと同じ要領でコミットする。
 今回のコメントは「星のレイヤーをビューに追加した。」とした。

 オリジナルへの変更履歴をFile>Source Control…>Repositories…メニューで表示させると、新しい更新履歴が追加されている。

$テン*シー*シー-34

 この履歴のディスクロージャを開くと、中にはView Changesというボタンがあり、この変更がどのようなものだったかを確認できる。

$テン*シー*シー-35

 コミットのときの要領で比較できる。

$テン*シー*シー-36

 また、以前の履歴のソースを元に、現在のソースを変更する事も可能。
 例えばプロジェクトウィンドウに戻り、SCMAppDelegate.mを選択した状態で右上のShow the version editorボタンを押す事で比較編集用の画面に切り替わり、下にあるバーで利用したい履歴を選べば、その履歴との比較ができる。

$テン*シー*シー-37

 そのまま、左側の画面でテキストを変更可能で

$テン*シー*シー-38

 変更すると下にLocal Revisionと出ていたバーはUnsaved Revisionとなり

$テン*シー*シー-39

 保存する(File>Saveメニュー)とLocal Revisionに戻る

$テン*シー*シー-40

 これが最新のテキストとなる。
 上の例ではQuartzCoreヘッダーのimportをやめているので、ところどころでエラーがレポートされている。

$テン*シー*シー-41

 ここまで確認したら、この変更は不要なのでFile>Source Control…>Discard Changes…を選べば、最後にコミットした内容に戻してくれる。

$テン*シー*シー-42

 特定のファイルだけ戻したい場合は、以下のようにファイルを選び右クリック(またはControlキーを押しながらクリック)で現れるコンテキストメニューからControl…>Discard Changes…を選べばよい。

$テン*シー*シー-43

プロジェクト

検討
 最初のSCMの説明の図で書かれているブランチやマージとはどのようなものか?
 そのやり方は?
 また、今のところディレクトリの移動なども、Xcodeからは対応できないようだ。
 この場合もターミナルからのコマンド入力を使う必要がある。これらの作業は次回。