HajimeHoshi.com

「詳解 Objective-C 2.0」勉強メモ (CHAPTER 05-01〜05-04)

05-05 の内容も追記した。

- (id)retain; // 参照カウントを増やす
- (oneway void)release; // 参照カウントを減らす

(P.90) retain メッセージで明示的に所有することを表さないと、参照カウントは増えない。なお alloc で生成したオブジェクトの参照カウント初期値は 1 なので、最初の所有者は気にしなくて良いみたいである (release は行う必要がある)。とすると、バランスしている時は (retain の数 + 1) = (release の数)、になるのだろうか。

oneway ってなんだろう、と調べたら P.450 に載っていた。非同期メッセージらしい。

- (void)dealloc
{
  // インスタンス変数のオーナーシップの放棄処理 (release)
  // および後始末処理
  [super dealloc]
}

(P.93) dealloc メソッドはオブジェクト解放時に呼ばれる。

id pool = [[NSAutoreleasePool alloc] init];
id foo = [[[Foo alloc] init] autorelease]; // 直近の pool に登録
// ...
[pool release];

(P.95) NSAutoreleasePool クラスで一時オブジェクトの自動メモリ管理が出来る。 autorelease メソッドを呼ぶと、その時点で最も最近に作成された自動解放プールに登録される。自動解放プール自体の autorelease メソッドを呼ぶとエラーになる。ところで、確実に解放させるために、 Java の finally や Go の defer みたいなのが欲しいのだけどもないのかなあ。

Cocoa の GUI アプリケーションの場合、 NSApplication がイベントハンドラを実行する前後で自動解放プールの生成、解放をしている。

(P.98) オーナーシップポリシー。 alloccopyXXXretain を使用した場合、オブジェクトのオーナーになる。オーナーは release または autorelease を呼ぶ責任が生じる。逆にオーナーでないオブジェクトがそれらを呼んではいけない。

- (id)temporaryValue
{
  id tmp = [[ComplexData alloc] initWithData:myValue];
  return [tmp autorelease];
}

(P.100) 一時的なオブジェクトを返すメソッドは、返す値に対して autorelease を呼んでから返す。このようにしたオブジェクトはオーナーが存在しないことになる。このようにするということは、メソッド呼び出し前後で自動解放プールを作らなければならない、ということになるのかな。グローバルに自動解放プールが存在したとしても、解放されるのがプロセス終了時になって効率が悪そう。(P.114) 局所的な自動解放プールを作るので合っている。

retain と release を使う場合
- (void)setMyValue:(id)obj
{
  [obj retain];
  [myValue release];
  myValue = obj;
}
if を使う場合
- (void)setMyValue:(id)obj
{
  if (myValue != obj) {
    [myValue release];
    myValue = obj;
  }
}

(P.100) オーナーシップの移動を伴うセッターの場合、代入元と代入先で同じオブジェクトを指していても大丈夫なようにする。オーナーシップの移動を伴わなければ単なる代入でよい。たいてい移動することはないと思うのだけども。(P.112) セッター以外の場所で、オブジェクトの所有権移動は大いに有り得る。セッターでも実はあるかもしれない。

+ (id)stringWithUTF8String:(const char *)bytes

(P.100) 一時オブジェクトを返すクラスメソッドの実装について。メソッド名はデータ (型) を表す名前で始める。このようなクラスメソッドをコンビニエンスコンストラクタと呼ぶ。中で alloc と初期化と autorelease が呼ばれている、というのが典型的な実装である。一時オブジェクトを返すクラスメソッドでない普通のメソッドでも、おそらくやることは同じだと思うのだけども、どうなのか。そもそもコンビニエンスコンストラクタの存在意義は、 P.108 を見るに、コンストラクタ + autorlease を一発で行うためのものである。それが自然に、一時オブジェクトを返すという実装になる、というだけの話である。一時オブジェクトを返すからコンビニエンスコンストラクタである、というわけではない。

(P.104) 常に解放してほしくないオブジェクトは、メソッド retainretainretainCount を上書き定義すればよい。たとえばシングルトンパターンなどの場合に使う。