concoquo

FlasherがObjective-Cをさわってみて

AcrionScriptとObjective-Cのはなし

悪い意味で生粋のASerがObjective-Cを書いてみて最初に戸惑ったこととか。

もともとFlashをアニメーションのツールとして使い始めた自分は今までにプログラミングの勉強をしたことがありません。stop()とかgotoAndPlay(2)とか書いているうちにちょっとずつActionScriptを覚えていったので、AS以外の言語に関する知識が一切無い。

そんな人間がObjective-Cをよちよち書き始めた時にいきなりつまずいたいろんなコトをつらつらと。

retain/releaseって?

ActionScriptは基本的にゆる〜い言語なのでメモリの管理とか特に考えずに使えます。それに比べてObjCはかなりシビアです。ベースがCなのでポインタの概念を理解する必要があるとか言われますが、というか本当は必要なのでしょうが自分は未だに理解できてません。

ですがそこまで深く理解しなくてもretainしたものをきちんとreleaseしてあげれば問題なく動きます。ミスると問答無用でオチますが。

//AS 初期化
var hoge:Hoge = new Hoge();
var array:Array = [a, b, c];
var bitmapData:BitmapData = new BitmapData(0,0);
//AS 明示的に参照を破棄したりBitmapDataなら解放してあげたり
hoge = null;
array = [];
bitmapData.dispose();

//ObjC 初期化 allocしたらretainされてる
Hoge *hoge = [[Hoge alloc] init];
//ObjC releaseして解放
[hoge release];
//ObjC autoreleaseしとけばreleaseの必要なし
hoge = [[[hoge alloc] init] autorelease];

基本的に二通りしかないので簡単だと思います。
メンバ変数のように保持しておきたい場合には、普通に初期化してdealloc時にまとめてreleaseする。
ローカル変数のように保持する必要がない場合は、autoreleaseをつけて初期化する。

見つからないよ!とか怒られる場合には手動でretainしてあげたりすれば多分だいじょうぶ。

型変換・キャストしたい

型に関しては感覚的に言うとASよりもかなり厳しめです。変数を作る段階で用途を考えてより吟味する必要がありそう。

//AS Class(hoge)とかhoge as Hogeとか
var str:String = "1";
var num:Number = Number(str);
var array:Array = [ 0, 1, 2];
var i:int = array[2] as int;

//ObjC (Class)hogeとか&とか
int i = 1;
float f = (float)i;
int ii;
[[array objectAtIndex:i] getValue:&ii];

NSStringがオブジェクト型なのに対してint,floatはプリミティブ型だから、ASでは普通にできる文字列→数値の型変換がObjCでは出来ない。

ここら辺は次の項目にも関係してくる。&を使う書き方は何て呼べばいいんでしょう。そもそもこの演算子はなんて呼べばいいの?

配列に数値が入れられない

NSArray,NSMutableArrayに入れられるのは参照型のみなのでプリミティブ型であるintやfloatやBOOLは入れられない。なのでここらへんのは数値を扱うオブジェクト型のクラスNSNumberを使ってごにょごにょします。

//プリミティブ型 → オブジェクト型
int i = 0;
NSNumber *n = [NSNumber numberWithInt:i];
//オブジェクト型 → プリミティブ型
int ii = [n intValue];

//配列に入れたり出したり
NSMutableArray *array = [[NSArray alloc] init];
BOOL b = YES;
[array addObject:[NSNumber numberWithBool:b]];
b = [[array objectAtIndex:0] boolValue];

こんなところで長時間つまずいていた時点でどんだけなレベルなのかがかなりバレバレなのですが、そういう事なのです。結構悩みました。

トレース(出力)したい

ASのtraceはObjCではNSLog。引数の1番目に出力したい文字列を、2番目以降に出力したい変数を列挙していきます。

//AS
var i:int;
var n:Number;
trace( i, n);

//ObjC
int ii;
float ff;
NSLog( @"ii=%i, ff=%f", ii, ff);

%から始まる記号は書式指定子とかフォーマット指定子とか呼ばれるもので出力したい変数にあった型のものを指定しないと怒られます。いっぱいあるみたいですが自分は%i(整数)、%f(小数)、%@(文字列)しか知りません。他のは書式指定子でググるとたくさん出てきます。

赤いエラーが出たら

黄色いエラーはとりあえず横に置いといてもいいとして、赤いビックリマークが出てコンパイル出来ない時にとりあえずチェックするポイント。

配列の最後にnil

NSArray,NSMutableArray共に要素の終端にnilが指定されていないとエラーが出ます。
これ意外とやっちゃいます。

//AS
var array:Array = [ "a", "b", "c"];

//ObjC
NSArray *array = [[NSArray alloc] initWithObjects:@"a", @"b", @"c", nil];

文字列は@から

そういうものなのでと割りきって。
@を付けることでNSString型として初期化される、みたいな事らしいです。

変数宣言で*アスタリスク

int,float,BOOLなどのプリミティブ型、汎用型のid、CGから始まるCoreGraphisc系のクラス(CGPointとかCGRectとか)、じゃないものはとりあえず全て変数名の頭に*をつけとけばいいと思います。
多少乱暴ですが。

行末にセミコロン

そのまんまですが、ASではスルーしてくれるセミコロン忘れもObjCではそうはいきません。
行末に必ず;を。

ごくごく初歩的な事ばかりなのですが、右も左も分からない状態ってかなりつらいですよね。他にも思い出したら追加します。