Objective--init
メソッドなどの初期化メソッドで実装されます。
よく見かけるのはこんな例ですね。
1 - (id)init 2 { 3 [super init]; 4 /* initialization code */ 5 return self; 6 }
しかしながら、基底クラスの初期化処理[super init]
の最中に、
メモリアロケーションの失敗などによって正常に初期化が行われなかった場合に備えて、次のようなエラーハンドリングを行った方が良いでしょう。
1 - (id)init 2 { 3 if(self = [super init]){ 4 /* initialization code */ 5 } 6 return self; 7 }
この辺の処理はXcodeなどが生成するひな形にも書かれていますね。
さて、ここからが本題ですが、上述の
/* initializa
の中で初期化が失敗したときは、どうしたら良いでしょうか。
仕様的には、初期化に失敗したら nil
を返す必要がありますが、
その際、途中までの段階で確保したリソースを解放する必要があるでしょう。
つまり、[super init]
の中で確保されたであろうリソースを解放する必要があります。
1 - (id)init 2 { 3 if(self = [super init]){ 4 /* initialization code */ 5 if(/* initializa tion failure */){ 6 /* release all resources */ 7 [super dealloc]; 8 return nil; 9 } 10 } 11 return self; 12 }
ということで、こんな感じに[super dealloc]
を呼び出して nil
を返します。
ここで、[super release]
を呼び出すと、
参照カウンタが0になり、 [self dealloc]
が呼び出されてしまうので注意が必要です。
[self dealloc]
を呼び出すようにする場合は、上述の
/* release all resources */
の中でリソースを解放せずに、[self dealloc]
の中で解放するようにする必要があります。
しかし、失敗した初期化処理の中で中途半端に確保したリソースを、
正しく解放する為には、[self init]
の内部で解放処理まで行った方が楽な気がします。
あるいは、以下の様に初期化済みのものだけ解放するようなコードを
[self dealloc]
に書いておくという手もあるかもしれません。
1 #define RELEASE(x) if(x) [(x) release] 2 3 - (void)dealloc 4 { 5 RELEASE(_something); 6 [super dealloc]; 7 }
こんなコードを見ると、なんだかノスタルジーを感じます。
ちなみに関係ないですが、このブログシステムでは、
Objective-
1 objective-c>> 2 /* Objective- C code */ 3 <<objective- c
[nil release] は、問題なく実行できるので、init の中で初期化処理に失敗した場合は、単に [self release] でいいんじゃないかと。
おーなるほど! それは便利ですねー。Thx!
まだまだC++脳だなあ。
deallocでsuperはあまり使わないでselfで使った方が使い出が良いですよ。
確かに。[nil release] がOkなら [self dealloc] で良さそうですねー。