XcodeでARCに変換できなかった時

XcodeでConvert to Objective-C ARCでARC化しようとした時に、Saveボタンを押しても変換されなかった。

スナップショットを作成できないのが問題らしく、調べたら.gitが邪魔らしい。.gitを外部に移動させるといいという情報にしたがって、.gitを移動して再度実行してみた。

が、失敗。Saveできない。

さらに検索すると、Developer Toolsをアンインストールして再度インストールするといいという情報が。試してみたが、やはりうまくいかない。

どうしようもなくなったが、ふと思い立って、試しにプロジェクトフォルダを他の場所に移動(この時はデスクトップ)に移動して、.gitを外部に出して、再度Saveしてみると成功。

何が悪かったか分からないが、とにかく変換できた。

mogeneratorを利用してCoreDataクラスを編集・再生成しやすくする

mogeneratorとは

mogeneratorはCoreDataエンティティのカスタムクラスを生成するツールです。

定義したエンティティをもとにクラスファイルをXcodeで生成しますが、開発者がコードを追加したあとで再度クラスファイルを生成すると、マージ作業が必要になります。

mogeneratorはこれを回避するためにFooエンティティに対して_FooクラスとそのサブクラスFooクラスを生成します。開発者はFooを書き換えることで、_Fooが何度生成されても独自コードをマージする必要が無くなります。

つまり懐かしのEOGeneratorのCoreData版です。

導入方法

mogeneratorのページからパッケージをダウンロードしてインストールします。/usr/bin/mogeneratorがインストールされます。

下記のようにモデルファイルを指定して、-Oでファイルを作成するフォルダを指定して実行すると、ファイルが生成されます。-Oを指定しない場合はカレントフォルダに生成されます。

$ mogenerator -m MyProject.xcdatamodeld/MyProject.xcdatamodel -O ./
4 machine files and 4 human files generated.

作成されたファイルをXcodeプロジェクトに追加します。今後カスタムロジックはFooクラスに追加し、エンティティに変更を加えた場合にはmogeneratorを再度実行して_Fooクラスを再生成します。

Xcode4でのユニットテストもGHUnitが良い

Xcode3まではGHUnitを利用していたが、Xcode4でユニットテストの実行が簡単になって、IDEでのサポートも増し、今回担当したプロジェクトでは新規でのXcode4での作業だったということもあり、下記の理由で標準のSenTestingKitを使ってみた。

  • プロジェクトを作成する時に自動的にユニットテストが組み込める
  • Command+Uですぐに実行できる
  • 実行結果がわかりやすくなった
  • 標準でデバッガを利用したデバッグが出来るようになった

使ってみたところ、IDEでのサポートが増したおかげで、ユニットテストが行いやすくなったのは実感できた。しかしいくつか不満がある。

  • 実行結果がオールグリーンの場合は何も表示されない
  • 非同期機能のテストが標準で行えない
  • アサーションの種類が少ない

といった点だ。どれもユニットテスにとって重要な点だ。

テストに失敗すると失敗個所が表示されるので良いのだが、すべて成功すると成功とは表示してくれない。いつ終了したのかも分かりにくい。ユニットテストっていうのはオールグリーンを確認することが重要だと気付いた。

今回のプロジェクトではNSURLConnectionを使用するような非同期機能は無かったので非同期機能のテストは行わなかったが、今後予定しているプロジェクトでは、SenTestingKitは標準では非同期テストが行えないので、GHUnitを利用して非同期機能のテストを行うことが必要となる。

アサーションの種類が多い方がテストを記述しやすく、分かりやすさも向上する。

結局のところ組み込みはプロジェクト作成時に一度行うだけで良いし、Command+Uでの実行もテストを行う時にターゲットを切り替えてテストを集中的に行えばいいので、GHUnitを使っていく方が良いという判断になった。

Xcode4がダウンロードできなかったらLicense Agreementを更新するといい

Xcode4が出ました。新しもの好きの私は早速ダウンロード…しようとしたらAccess Denied。

ネットで調べたらキーチェーンがどうちゃらこうちゃら。その通りに調べてみても問題なし。

で、ADCサイトをブラウズしてたらiOS Developer Program License Agreementのアップデートをしてくれと表示される。ハッ!と思って、アップデートして、再度Xcode4をダウンロードしてみたら正常に開始。

Twitterで他にも同様の問題が発生しているとつぶやいてる人に、この現象を伝えたら、その人もLicense Agreementの更新でダウンロードができたと返事が。

ということで、Xcode4ダウンロードでAccess DeniedになるのはiOS Developer Program License Agreementの更新をしてなかったのが原因みたい。

CinderのXcodeプロジェクトの作成からキャンバスの描画をしてみる

Download | CinderからCINDER FOR MAC OS Xをダウンロード。114MB。

ダウンロードしたcinder_0.8.2_mac.zipを解凍。まずはWelcome.htmlを見る。samplesにあるサンプルを試してみる。サンプルが57個あるので、かなり研究しやすそう。

TinderBoxでXcodeプロジェクトを作成する。cinder/tools/TinderBoxを起動。

201011281949.jpg

For Sureをクリック。ファイル選択画面になるので解凍したcinderフォルダを指定。更にSaveパネルが表示されるので、Xcodeプロジェクト名を指定。FirstCinderと指定した。プロジェクト詳細画面になるのでCreateボタンをクリック。

Xcodeプロジェクトが作成されたので、プロジェクトを開いて実行してみる。
201011281956.jpg

201011281957.jpg

とりあえず真っ黒。

コードを見てみる。FirstCinderApp.cppというファイルがメインのファイル。内容は以下。

#include "cinder/app/AppBasic.h"
#include "cinder/gl/gl.h"
 
using namespace ci;
using namespace ci::app;
using namespace std;
 
class FirstCinderApp : public AppBasic {
  public:
	void setup();
	void mouseDown( MouseEvent event );
	void update();
	void draw();
};
 
void FirstCinderApp::setup()
{
}
 
void FirstCinderApp::mouseDown( MouseEvent event )
{
}
 
void FirstCinderApp::update()
{
}
 
void FirstCinderApp::draw()
{
	// clear out the window with black
	gl::clear( Color( 0, 0, 0 ) );
}
 
CINDER_APP_BASIC( FirstCinderApp, RendererGl )

正規のnamespaceはcinder::だが、シノニムのci::を使うと短くて良い。ということでci::とci::appを利用するように宣言されている。

void setup()で変数を初期化。void update()で変数を更新。void draw()で描画。updateとdrawはCinderプロジェクトの中心になる。setup→update→draw→update→draw→…。

void prepareSettings()を作成するとCinderの設定を修正することができる。prepareSettingsはオプション。CinderのデフォルトWindowサイズは640×480でフレームレートは30。例えばこれを100×100と60に変更するには

void FirstCinderApp::prepareSettings( Settings *settings ){
    settings->setWindowSize( 100, 100 );
    settings->setFrameRate( 60.0f );
}

とする。と、こうなる。

201011290851.jpg

これでは狭いので、800×600に変更。

draw()ではgl::clear( Color( 0, 0, 0 ) );でキャンバスを黒で塗っている。Color(1.0,1.0,1.0)で白になる。void clear (const ColorA &color=ColorA::black(), bool clearDepthBuffer=true)なので、引数に何も指定しなければ黒が利用される。また、depth bufferもクリアされる。

float gray = sin( getElapsedSeconds() ) * 0.5f + 0.5f;
gl::clear( Color( gray, gray, gray ), true );

とすると、grayが0.0から1.0を行き来して描画される。つまり白と灰色と黒を行き来する。