記事一覧

アイコンが急に真っ白に!

今まできちんと表示されていたアプリのアイコンが急に真っ白に。
なぜだ!!?? ターゲットの設定とかInfo.plistとかいじったからその影響か!?
と思って悩むこと十数分。

なんのことはない、ちょっと前にアイコンのデザインを変更したときに間違えて psd データを Icon.png として保存してました;
たまにやるんだよなコレ;

バージョン違いのバイナリを作る

iPhoneで、有料バージョンと無料バージョンみたいな複数のバージョンを作りたい場合、それぞれ用のバイナリを作らなければいけないわけですが、そんな場合は、XCodeでターゲットを2つ作って、それぞれに "OTHER_CFLAGS" を設定すればいいんですね。

http://www.codza.com/free-iphone-app-version-from-the-same-xcode-project

これでソースの冒頭に #define FREEVERSION とか宣言したのと同じ事になるので、あとはソース中に適宜
#ifdef FREEVERSION
...(フリー版特有の処理)
#endif
とか書けばよいです。

ここで注意なのが、ターゲット編集時、編集対象となる構成を「すべての構成」にして Debug/Build/その他(Ad-hoc用など) すべてについて変更しておかないと、Debug構成のときは無料バージョン設定になってくれるけど、Releaseにしたら急に有料バージョン設定になっちゃって「???」な事態になります。

あと、フラグの書き方は、
-D(フラグ名)
で、フラグ名が大文字だと
-DFREEVERSION
とかくっついた格好になるので -D を見落としやすいかもしれません。

Objective-Cでクラス変数

Objective-C はいわゆるクラス変数というのがないから、それ相当のものが必要なら static 変数を定義してそのファイル内で静的に確保される変数を作りなさい、というのだけど、いざそのようにしてみると一応動くものの "defined but not used" という警告がやたらめったら出る。
なんじゃいこれは、と思って調べたら出てきた。

http://stackoverflow.com/questions/1603246/why-is-xcode-reporting-a-defined-but-not-used-warning-for-my-class-variable

static変数宣言をヘッダファイルの方に書いてしまうと #import で呼ばれるたびに変数を確保してしまうんだそうで。
僕のプロジェクトはかなり #import が入り乱れているので(二重取り込みを気にしなくていいから基本多めに書いてしまう)、static 変数ひとつあたり10個とか警告が出る;

解決策は、static 変数を .m ファイルの方に書くこと。
なーんだ簡単。

NSTimer

うーん、NSTimerは微妙に難しいなぁ〜
インスタンスは保持したまま停止/再開ってどうやるんだ。
invalidateするとインスタンス自体消滅しちゃうっぽいし。
スケジュールをずっと先に設定するとか?
それもなんか不毛なのでひとまず自前で bool timerWorking なるものを用意して timerCallback の冒頭で
if(!timerWorking){return;}
とかしてある。なんか納得いかんけどひとまずそんなにパフォーマンスも落ちてないっぽいしいいかな・・・・

そもそも cocosNode 絡みだったら schedule: が使えるんだけど、シーンを越えて保持したいオブジェクトだから cocosNode に紐付いてると不便なんだよねえ。


('10 8/2追記)
invalidate 済みの myTimer へメッセージを送ろうとしたときに Bad Access になるのを回避したいだけなら
[myTimer invalidate];
した後に
myTimer = nil;
とすれば良いらしい。ウチの場合もこれで良かったんだな・・
http://www.iphonedevsdk.com/forum/iphone-sdk-development/22040-exe-bad-access-error.html

Landscape な cocos2dのウィンドウにUITextFieldを貼り付ける

fieldWidth, fieldHeight はテキストフィールドのサイズ、
fieldX, fieldY はLandscape状態で画面左上から見た座標。M_PIは定数πでありんす。

UITextField* field = [[UITextField alloc]
initWithFrame:CGRectMake(320-fieldY-fieldHeight, fieldX, fieldHeight, fieldWidth)];
field.text = @"text";
field.transform = CGAffineTransformMakeRotation(2.0/M_PI);
field.bounds = CGRectMake(fieldX, fieldY, fieldWidth, fieldHeight);
[[[Director sharedDirector] openGLView] addSubview:(UIView*)field];

UITextField の貼り付け自体はあっけないくらい簡単だった。
でも Landscape 方向だととたんにややこしくなりますね。
座標が左下原点ってのも非常に馴染みがなくてやりずらい・・・

あと、boundsの設定は自信無し; とりあえず動いているので放置してあるが・・・

TouchDispatcher @ cocos2d

cocos2d の TouchDispatcher を使ってタッチの振り分けをしようと思ったらうまく動かない。
cocos2dフォーラムとかも調べてみたがだいたいありがちな対策はとってある・・・
と、途方にくれていたのだけど、突然 priority の値設定がテキトーだったことに気づいていじってみたら動いた。
どうやらディスパッチを特に指定しないで受け取った場合の priority が 0 で、これより優先する場合は負の数を指定しないといけないようですね。というわけで、
[[TouchDispatcher sharedDispatcher] addTargetedDelegate:self priority:-1 swallowsTouches:YES];
が正解か。

あと、ここでswallowsTouchesを指定するとすべてのタッチが飲み込まれてしまうかというとそうではなくて、
ccTouchBegan で return NO; を返すと優先度の低いデリゲートへとタッチをスルーできるようだ。

続・ファイル読み込み

結局 Objective-C++ で対応することに決定。
なんか負けた気分なのはなぜだ;
しかし、Objective-C++ 思いのほか使い勝手がいいな・・・。

で、NSBundle の pathForResource:ofType: でファイルパスを取得して NSString で処理しようと思ったらそもそもパスが取得できてないことが発覚。
プラグイン内のリソースは [NSBundle mainBundle] で取得できないのね;
[NSBundle bundleWithIdentifier:@"com.company.pluginName"]
としたら取得できました。

mainBundle だと、ホストアプリケーションのリソースを取ってくることになるのかしら??

あと、XCode上で Foundation フレームワークを追加しないとリンクエラーになるのね。
でも Foundation/Foundation.h の include はわざわざ書かなくて良いようだ。

ファイルの読み込み

iPhoneの方がちょうど一山越えたところなので久々にAudioUnitプラグイン基礎を見直しているのだけど、やはり基礎的なところがまったく分かってない;
外部テキストファイルの読み込みってどうやるんだ!??
Objective-C なら NSString の stringFromContentsOfURL:encoding:error:
でイッパツなので、CFString の対応する関数とかを使えば・・・と思ったのだけど、そんな単純なものではないらしい・・・
fopen / fscanf とか使うの!? それはそれでファイル名のエンコーディングとかどうするんだ・・・
やはり基本的なことがまったく分かってないようだ・・

provisioningの更新

三ヶ月ごとに切れる開発者用provisionですが、更新の手続き自体は、
iPhone Provisioning Portal で Provisioningのページに行って renew ボタンを押す → 新しい .mobileprovision が出来たらダウンロード、なんですが、
(参考: http://iced.tea-nifty.com/lemon/2009/10/provisioning-pr.html
僕が一瞬つまづいたのが、

(1)期限が切れてからでないと renew できない(微妙に不便;)
(2)XCode上だけでなく、iPhone上でも期限切れした .mobileprovision を削除しないと、そっちを読みに行ってしまって期限切れエラーになる

の2点。 (1)の仕様のせいで出かける間際に作業するハメになったところに(2)の仕様で引っかかってえらい焦った;

むむ。

TilemapAtlasはもうdepricatedだったのね;
でもTMXTilemapが思いのほか使いやすくて良かった。