iPhone用アプリのコード解読で、重要になるObjective-Cの項目
<特別なコンパイラディレクティブ>
property
・.hファイルで、@propertyと記述すると、setterとgetterが
setterはsetHogeとして、getterはhoge.として定義されたことになる。
※@propertyはシグネチャが定義されただけで、
実装は、.mファイルに別途、記述しなければならない
synthesize
・.mファイルで、@synthesize hogeと記述すると、
getterとsetterの実装を定義してくれる。@propertyの実装版。
多くの場合、@propertyと対で使用される。
<引数セパレータのメリット>
・[test setWidth:5 height:6 depth:7]; のように、
呼び出し側でも何をしているのかがわかる。
※一般的な関数呼び出しだと、test.setSize(5, 6, 7);のように、
呼び出し側だけ見ても、何をしているのかがわかりにくい。
Objective-Cのメモリ管理について
<メモリ管理に関する内容>
リファレンスカウンタの存在意義
・オブジェクトの変数への代入の際には、オブジェクトそのものではなく
ポインタを渡すようになっている
⇒サイズの大きいオブジェクトのコピーを避けて、
1つのオブジェクトを複数の変数で共有し、無駄なメモリを抑制している
・したがって、共有している変数のどれかが勝手に解放すると、
他の変数にも影響が出てしまう。
そこでリファレンスカウンタという仕組みが導入されている。
リファレンスカウンタの仕組み
参照している変数の数が0になったら、初めてオブジェクトを解放するという仕組み
※ただし、参照数は自動的に更新されるのではなく、
メソッドを呼んで明示的に増加減少させる必要あり。
allocで自動的に+1、releaseで-1されるなど。autoreleaseというのもある。
dealloc
・deallocは、明示的に呼び出してはいけないが、
インスタンス変数を解放するために、オーバーライドしておく必要がある。
※deallocは、オブジェクトを強制的に解放するメソッドで、
内部でリファレンスカウンタが0になったら自動的に実行される関数
メモリの管理の意義~
iPhoneではガベージコレクションが使えない(2009/7/23時点)
メモリリークが発生しないようにきちんと管理することが必要
仕組み~
リファレンスカウンタを使う
リファレンスカウンタは、retainメソッドで+1, releaseメソッドで-1される
リファレンスカウンタの作法~
1.インスタンス変数で別のクラスのインスタンスを保持するとき、
(インスタンス変数がオブジェクト型の場合)
勝手に消されないようにsetterメソッドでretainするのが通例。
2.アプリケーションの具体的なロジックをmain関数に直接記述することは
ほとんどない。つまり、プログラムのメモリ管理の責任範囲は、
クラスとメソッドの単位で切り離して考えればよい。
(a) クラスは、インスタンス変数の責任を持つ
⇒setterかdeallocでrelease
(b) メソッドは、メソッドの内部で生成したオブジェクトに責任を持つ
⇒メソッドの中だけで不要となったら、その場でrelease
メソッドの外でも必要ならば、クラスのインスタンス変数にセット
⇒(a)よりクラスの責任となる
※上記はガベージコレクションを使用しない場合の作法である
autoreleaseについて~
1: - (NSObject *)createObj1 {
2: NSObject *obj = [[NSObject alloc] init];
3: return obj;
4: }
このようなメソッドがあるとき、その場でobjを解放すると呼び出し側で
使用不能になるし、deallocで解放しようにもインスタンス変数に
保存していないので解放できない。
このケースでは、autoreleaseメソッドによって、後で自動解放されるように
予約しておく。autoreleaseは、いちいちreleaseのタイミングを考慮しながら
実装するのが面倒だったり、うっかりミスによる解放忘れ防止にも有効。
autoreleaseの使い方~
(Ⅰ) NSAutoreleasePoolクラスのインスタンスを生成する
これ以降、autoreleaseが実行されたオブジェクトは、
NSAutoreleasePoolのインスタンスに登録される
(Ⅱ) NSAutoreleasePoolクラスのdrainメソッドを実行すると、
(Ⅰ)で登録したインスタンスが自動で解放される
Objective-Cの配列について
C言語にあるような array[5]; のような配列だけでなく、
Objective-Cの配列オブジェクトとして、
「NSArray」と「NSMutableArray」(オブジェクト配列)、
「NSDictionary」と「NSMutableDictionary」(連想配列)などがある。
C言語の配列は要素数が固定となっているなどの制約があるので、
配列の要素の追加・挿入・削除、配列自体の情報習得など
便利な機能を追加したものになる
便利な機能の例
1.あるデータが入っている配列のインデックスを返す「indexOfObject:」
2.2つの配列の要素が同じものであるかを判定する 「isEqualToArray:」
連想配列は、Objective-Cでは「ディクショナリ(辞書)」と呼ばれている
Objective-Cの配列オブジェクトは、必ず、終端にnilを入れて
終端位置を明示しなければならない
Objective-Cの配列オブジェクトは、その要素がクラスオブジェクトでなければ
ならないという点に注意。
文字列ならば、@"(文字列)", 数値ならば、[NSNumber numberWithInt:4]
のようにして格納する必要がある。
その他
Objective-Cの糖衣構文
test.myProp = 5; // [test setMyProp:5]; と同じ
int i = test.myProp; // int i = [test myProp]; と同じ
@"(文字列)" //文字列がNSStringクラスのオブジェクトであることを表す
Objective-Cのクラスで「NSXxxx」と「NSMutableXxxx」という
組み合わせはすべて、インスタンスを直接変更できないクラスと
変更可能なクラスの組み合わせである。
例)「NSArray」と「NSMutableArray」、
「NSString」と「NSMutableString」など
また、「NSMutableXxxx」は「NSXxxx」のサブクラスとなっていて、
基本的なメソッドをそのまま利用できることが多いようだ。
Objective-Cのクラスで「initWith~」と「xxxWith~」(xxxは"String"や
"array"など)という組み合わせが存在することがある。
これは、前者がreleaseのタイミングを自分で考えなければならないもので、
後者がalloc→init→autoreleaseまでを自動で行ってくれるクラスである。
例)「initWithCString:encoding」と「stringWithCString:encoding」
「カテゴリ」を使用して、カテゴリ分けことには、
(1) 開発作業の分担
(2) 膨大なクラスの分割、
(3) 既存のクラスへの(継承よりも簡単にできる)機能の追加
という意義がある
クラスをカテゴリ分けするときは、(クラス名).h と (クラス名).m,
(クラス名+カテゴリ名).m ,・・・ というファイル名を付けるのが一般的
メソッドポインタを使用すると、普通のC言語の関数として
呼び出せるようになるが、これはメッセージ通信方式よりも軽いので、
重い処理(画像処理など)を行う場合に有効である
@protocolは、クラスがある処理に対応することを示すために用いるが、
静的な宣言であるため、プロセス間通信が速くなるという情報があった
http://journal.mycom.co.jp/column/objc/009/index.html