4

私は、例外安全なコードを実現するために、次のようなコードを書いていることに気づきました。

Container* container = [Container new];
@try {
    while(someCondition) {
        ElementType* value = [someObject createObjectFromStorage];
        [container add:value]; // container retains object
        [value release];
    }

    [_container release];
    _container = [container retain];
} @finally {
    [container release];
}

Objective-Cで従うべき他のより簡潔なパターンはありますか?

4

2 に答える 2

8

オブジェクトを解放したことを確認するだけの場合autoreleaseは、おそらく十分です。Xcode4.2の新しい自動参照カウントオプションを調べることもできます。

すべてのObjective-Cオブジェクトはヒープに割り当てられるため、Objective-Cは一般にRAIIには適していません。これは、オブジェクトの存続期間が特定のスタックフレームに明示的に関連付けられていないことを意味します。したがって、オブジェクトを割り当てたメソッドの最後で割り当てが解除されているオブジェクトに依存することはできません。

また、Cocoaフレームワークは、予期されたエラー状態ではなく、プログラマーエラーを示すためにのみ例外を使用することに注意する必要があります。Appleの「例外プログラミングガイド」のドキュメントから:

重要:プログラミングの例外の使用、または範囲外のコレクションアクセス、不変オブジェクトの変更の試行、無効なメッセージの送信、ウィンドウサーバーへの接続の喪失などの予期しないランタイムエラーの使用を予約する必要があります。通常、これらの種類のエラーは、実行時ではなくアプリケーションの作成時に例外として処理されます。

エラー状態を処理するために例外を使用する既存のコード本体(サードパーティライブラリなど)がある場合は、Cocoaアプリケーションでコードをそのまま使用できます。ただし、予想される実行時例外がこれらのサブシステムからエスケープされて、呼び出し元のコードに到達しないようにする必要があります。たとえば、解析ライブラリは、内部で例外を使用して問題を示し、深く再帰的になる可能性のある解析状態からの迅速な終了を可能にする場合があります。ただし、ライブラリの最上位でこのような例外をキャッチし、適切なリターンコードまたは状態に変換するように注意する必要があります。

実際、例外は例外的な場合にのみ使用されることを目的としているため、デフォルトでは、新しく導入された自動参照カウントは、例外をスローするときにオブジェクトを意図的にリークします。

標準のCocoaの規則では、例外はプログラマーエラーを通知し、回復することを目的としていません。コードの例外をデフォルトで安全にすると、通常は例外の安全性を実際に気にしないコードに、実行時間とコードサイズに厳しいペナルティが課せられます。したがって、ARCで生成されたコードは、デフォルトで例外でリークします。これは、プロセスがとにかくすぐに終了する場合は問題ありません。例外からの回復を気にするプログラムは、オプションを有効にする必要があります。

Cocoaフレームワークを使用したプログラミングは、そのフレームワークのイディオムに準拠していれば、はるかにうまくいきます。つまり、プログラマーエラーに対してのみ例外を使用し、予想されるランタイムエラーを。で処理しますNSError。ほとんどのCocoaプログラマーは、コードがそもそも例外をスローしないため、例外セーフなコードを書くことを心配することはありません。あなたはそれに続くのが良いかもしれません。

于 2011-12-07T21:46:24.970 に答える
1

自動リリースは標準パターンです。

Container* container = [[Container new] autorelease];
while(someCondition) {
    ElementType* value = [someObject createObjectFromStorage];
    [container add:value]; // container retains object
    [value release];
}

[_container release];
_container = [container retain];

ただし、これはメモリ管理にのみ適用されます。RAIIの完全な代替品ではありません。Objective-Cには、RAIIを完全に置き換える一般的に使用されるパターンはありませんが、ブロック(または多分)を使用して独自のコードベースでそのようなパターンを作成する__attribute__((cleanup))ことはできます。

newパターンについて話している間、ちなみに…一般的なパターンは、、、、という単語で始まらないalloccopyまたはmutableCopy自動解放されたオブジェクトを返すメソッドです。仮想メソッドをに変更し、-objectFromStorageそのパターンに従うようにした場合、ループはさらに簡潔になります。

while(someCondition) {
    [container add:[someObject objectFromStorage]];
}
于 2011-12-07T21:26:17.870 に答える