Objective-Cでオブジェクトを初期化する処理は、-init
メソッドなどの初期化メソッドで実装されます。
よく見かけるのはこんな例ですね。

objective-c>>

  • (id)init
    {
    [super init];
    /* initialization code */
    return self;
    }
    <<--

しかしながら、基底クラスの初期化処理[super init]の最中に、
メモリアロケーションの失敗などによって正常に初期化が行われなかった場合に備えて、次のようなエラーハンドリングを行った方が良いでしょう。

objective-c>>

  • (id)init
    {
    if(self = [super init]){
    /* initialization code */
    }
    return self;
    }
    <<--

この辺の処理はXcodeなどが生成するひな形にも書かれていますね。

さて、ここからが本題ですが、上述の
/* initialization code */
の中で初期化が失敗したときは、どうしたら良いでしょうか。
仕様的には、初期化に失敗したら nil を返す必要がありますが、
その際、途中までの段階で確保したリソースを解放する必要があるでしょう。
つまり、[super init]の中で確保されたであろうリソースを解放する必要があります。

objective-c>>

  • (id)init
    {
    if(self = [super init]){
    /* initialization code /
    if(/
    initialization failure /){
    /
    release all resources */
    [super dealloc];
    return nil;
    }
    }
    return self;
    }
    <<--

ということで、こんな感じに[super dealloc]
を呼び出して nil を返します。
ここで、[super release] を呼び出すと、
参照カウンタが0になり、 [self dealloc]
が呼び出されてしまうので注意が必要です。
[self dealloc]を呼び出すようにする場合は、上述の
/* release all resources */
の中でリソースを解放せずに、[self dealloc]
の中で解放するようにする必要があります。
しかし、失敗した初期化処理の中で中途半端に確保したリソースを、
正しく解放する為には、[self init]
の内部で解放処理まで行った方が楽な気がします。
あるいは、以下の様に初期化済みのものだけ解放するようなコードを
[self dealloc]に書いておくという手もあるかもしれません。

objective-c>>
#define RELEASE(x) if(x) [(x) release]

  • (void)dealloc
    {
    RELEASE(_something);
    [super dealloc];
    }
    <<--

こんなコードを見ると、なんだかノスタルジーを感じます。

ちなみに関係ないですが、このブログシステムでは、
Objective-Cのソースコードを以下のような記法でSyntax highlightさせる事ができます。

pre>>
objective-c>>
/* Objective-C code */
<<objective-c
<<pre

posted by genki genki on Mon 6 Oct 2008 at 22:09 with 4 comments