Objective-C/atmark

Last-modified: 2010-10-22 (金) 13:25:59

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