2012-04-17
cocos2dでSenTestingKitをつかったUnitTestを行う場合の注意点とか
cocos2d | |
誰かがもう本に書いてしまっていそうな内容ですが、気にしない。
cocos2dのprojectをSenTestingKitを使った自動テストに掛けた場合、テスト以前の想定外のエラー等が発生するケースがあります。それらのケース全てに対応できるかどうかは不明ですが、ある程度のカバーは可能になるであろうと思われる手順を以下に。
Build用に追加設定を行う
UnitTestを行う場合、ProjectのTargetに「Add Target」から「Cocoa Touch Unit Testing bundle」を指定するわけですが、これだけでは正常にテストできません。
- 追加したTargetのBuild Phaseから、「Compile Sources」にcocos2dのライブラリ(.mと.c)を一通りと、開発しているアプリのソース(.m)を一通り追加します。
- Build Settingsから、「Other Linker Flags」に「-lz」と入れます。
- Build Phaseの 「Link Binary With Libraries」に以下を追加します。(開発しているアプリの同じ構成+SenTestingKit)
- AudioToolBox.framework
- AVFoundation.framework
- QuartzCore.framework
- OpenAL.framework
- OpenGLES.framework
- CoreGraphics.framework
- SenTestingKit.framework
- UIKit.framework
- Foundation.framework
基本は、開発しているTargetと同じ構成にします。
Test時にGL_VENDOR等がnullにならないようにする
test時にwindowを生成していないことが原因です。ccMacros.h にある CC_DIRECTOR_INIT() を呼び出します。
#import <SenTestingKit/SenTestingKit.h> #import "ccMacros.h" @interface GOKTBase : SenTestCase { UIWindow *window; } @end @implementation TestBase - (void)setUp { [super setUp]; CC_DIRECTOR_INIT(); } - (void)tearDown { CC_DIRECTOR_END(); [super tearDown]; } @end
テスト用に上記のような内容のベースクラスをはさんでしまうのも手です。
これで、テスト自体はコケることなく実行されるようになります。
cocos2dの一部ソースコードをTest Targetでも問題なく動くように修正する
CCSpriteなどを使ったファイルにて、CCTextureCacheにイメージを追加しようとして失敗するケースがあります。これは、Main BundleのパスがアプリとUnitTestで異なることをcocos2d側では考慮されていない為です。(参考:OCUnit & NSBundle)
- CCFileUtils.m
+(NSString*) fullPathFromRelativePath:(NSString*)relPath resolutionType:(ccResolutionType*)resolutionType { NSAssert(relPath != nil, @"CCFileUtils: Invalid path"); NSString *fullpath = nil; // only if it is not an absolute path if( ! [relPath isAbsolutePath] ) { // pathForResource also searches in .lproj directories. issue #1230 NSString *file = [relPath lastPathComponent]; NSString *imageDirectory = [relPath stringByDeletingLastPathComponent]; - fullpath = [[NSBundle mainBundle] pathForResource:file + fullpath = [[NSBundle bundleForClass:[CCFileUtils class]] pathForResource:file ofType:nil inDirectory:imageDirectory]; }
これでCCTextureCacheで問題が発生することはなくなります。
2010-01-11
CoreDataの構成
CoreData | |
サンプルのCoreDataBooksを弄くり通して移植とか試みた結果、どこがどうなってるのかようやく把握できた感じなのでメモ。
そもそも何故分かりづらいのか
CoreDataはSQliteをObjective-Cのみで操作できることにメリットがあるわけですが、その操作を行うためのクラス名、取り扱い方に問題があります。
イメージしずらいネーミング
各クラスの解説を読むと判明しますが、実際には他の言語で使われているDBとの接続を行うための各種クラスと、CoreData関連クラスがやってることには、あまり違いはありません。ただ、それらのクラスと余りに剥離したネーミングというのが一つ。
複数のDBの接続を同時に取り扱っている
もう一つは、あくまでCoreDataは「複数のDBとそれらDBとの接続情報」をひとまとめにした代物であるため、他の言語でのDBと同じ感覚で取り扱うとズレが生じるということ。
TableView専用というわけではないNSFetchedResultsController
さらにもう一つ、NSFetchedResultsController自体はCoreDataから取得したデータの配列をキャッシュしているコントローラであり、別にUITableViewController専用のオブジェクトではない、ということ。
CoreDataのコンテキスト構成
コンテキスト以下の構成図を貼ってみます。
ColumnもといEntityを追加したい場合にはNSManagedObjectModelへの操作、接続するDBを増やしたい場合にはNSPersistentStoreを追加するといった形です。
NSPersistantStore追加の際の実DBファイル
接続するDBを増やす場合にはNSPersistentStoreを追加するわけですが、実体のファイルもその際に自動で生成されています。
データ追加
NSEntityDescriptionで追加先のEntityを指定すると生成されるオブジェクト(レコード相当)に値を入れて保存、という流れです。DBへのレコード追加をSQLを直接触れずに行う形です。
データの読み込み
NSFetchedResultsControllerを生成した時点で、データの取得ができ上がるため、あとは取得したデータの配列からインデックスを指定して取得という流れ。
まとめ
NSManagedObjectContextを構成する際の煩雑さも原因だと思うので、NSManagedObjectContextまでの生成過程を一つのクラスにして分離したほうが、なにかと分かりやすいかと思います。
あと、これらを一つ一つ確かめていくとどこかで同じ構成をみたような感覚があったのですが、PerlにおけるDBIx::Classがそれでした。どんな感じなのかは、
を読むと分かりやすいと思います。
2009-10-10
2009-10-03
ビルド時にClangを自動で実行させる
現行の最新Xcodeは、ソースコードの静的解析を行うClangがメニューから実行できるようになっています。逐一設定実行する手間が省けて助かる事間違い無しなんですが、毎回clangのために余計な操作をするのは本当面倒です。
余り知られていませんが、このClangも自動で実行できるようになっています。デフォルトで実行がONになっていれば良いとは思うんですが、多分それだと初学者の壁が只管高くなるとかそんな具合だと思います。
設定方法
- Xcodeのメニューから、「プロジェクト->プロジェクト設定を編集」の順に選択します。
- ビルドオプションの「静的アナライザを実行」にチェックをいれます。
2009-09-22
CoreDataを使う場合のトラブルシュート
CoreData | |
Macでのデータベース取り扱いが楽になるというCoreDataですが、確かにMac用アプリでは開発が楽になるようです。というのも、iPhoneでは色々とコーディングが要求されてしまうから。結果、はまってしまうところがでて、それが解消されにくい場合は、思い切ってFMDBで行うほうが幸せかもしれません。
試行錯誤しつつ組み込みに挑戦していますが、エラーが完全には解消されず詰まっている状態です。現状に至るまでに分かったいくつかのはまりポイントについてまとめてみます。
+entityForName: could not locate an NSManagedObjectModel for entity...
xcdatamodel内でEntityの名称が間違っている場合や、NSEntityDescriptionを生成する以前にNSPersistentStoreCoordinatorなどを適切に生成していない、など。
Z_PKなどの、頭にZが付くコラムが足りないと表示される
sqliteファイルを手動作成した場合、CoreDataに用いるsqliteのテーブルおよびコラム名は、イニシャルがZで始まる必要があります。(NameならZNameになる、など)
また、CoreDataが用いる専用のテーブルを作成する必要もあります。
参考:Core Data Error: Can’t Find Model for Source Store
CREATE TABLE Z_PRIMARYKEY (Z_ENT INT Primary Key, Z_NAME VARCHAR, Z_SUPER INTEGER, Z_MAX INTEGER);
CREATE TABLE Z_METADATA (Z_VERSION INT Primary Key, Z_UUID VARCHAR(255), Z_PLIST BLOB);
Entityを収めたテーブルにも、システムが管理に用いるためのコラムの追加が必要です。
Z_OPT INTEGER
Z_PK INTEGER PRIMARY KEY