基本:retainCountを使用しない公式の理由は何ですか?
retainCount
自動解放管理は最も明白です。 によって表される参照の数が、ローカルまたは外部 (セカンダリ スレッド上、または別のスレッドのローカル プール内) の自動解放プールにあることを確認する方法はありません。
また、リークやより高いレベルの参照カウント、および自動解放プールが基本レベルでどのように機能するかについて問題を抱えている人もいます。彼らは、適切な参照カウントを (あまり) 考慮せずに、または参照カウントを適切に学習せずにプログラムを作成します。これにより、プログラムのデバッグ、テスト、および改善が非常に困難になります。修正には非常に時間がかかります。
(クライアント レベルで) その使用を思いとどまらせる理由は 2 つあります。
1) 値は非常に多くの理由で異なる場合があります。スレッドだけでは、それを信頼できない十分な理由があります。
2) 正しい参照カウントを実装する必要があります。retainCount
不均衡な参照カウントからあなたを救うことは決してありません。
それが役立つかもしれない状況はまったくありますか?
実際、独自のアロケータまたは参照カウント スキームを記述した場合、またはオブジェクトが 1 つのスレッド上に存在し、それが存在する可能性のあるすべての自動解放プールにアクセスできる場合は、意味のある方法で使用できます。外部 API と共有します。これをシミュレートする簡単な方法は、スレッドが 1 つ、自動解放プールがゼロのプログラムを作成し、「通常の」方法で参照カウントを行うことです。「学術的」な理由以外で、この問題を解決したり、このプログラムを作成したりする必要があるとは考えにくいでしょう。
デバッグの補助として: これを使用して、保持カウントが異常に高くないことを確認できます。このアプローチを採用する場合は、実装の差異に注意してください (一部はこの投稿で引用されています)、それに依存しないでください。テストを SCM リポジトリにコミットすることさえしないでください。
これは、非常にまれな状況で有用な診断になる場合があります。以下の検出に使用できます。
過剰保持: プログラムが割り当てに到達できる場合、保持カウントに正の不均衡がある割り当ては、リークとして表示されません。
他の多くのオブジェクトから参照されるオブジェクト: この問題の 1 つの例は、マルチスレッド コンテキストで動作する (変更可能な) 共有リソースまたはコレクションです。このリソース/コレクションへの頻繁なアクセスまたは変更は、プログラムの実行に重大なボトルネックをもたらす可能性があります。
自動解放レベル: 自動解放、自動解放プール、保持/自動解放サイクルにはすべてコストがかかります。メモリの使用や増加を最小化または削減する必要がある場合は、このアプローチを使用して過剰なケースを検出できます。
Bavarious のコメントから (以下): 高い値は、無効な割り当て (dealloc されたインスタンス) を示している可能性もあります。これは完全に実装の詳細であり、製品コードでは使用できません。ゾンビが有効になっている場合、この割り当てを通知するとエラーが発生します。
代わりに何をすべきですか?
でメモリを返す責任がない場合self
(つまり、アロケータを作成していない場合) は、そのままにしておいてください。それは役に立ちません。
適切な参照カウントを学ぶ必要があります。
release と autorelease の使用法をよりよく理解するには、いくつかのブレークポイントを設定し、それらがどのように使用されるか、どのような場合に使用されるかなどを理解してください。参照カウントを正しく使用する方法を学ぶ必要がありますが、参照カウントが役に立たない理由を理解するのに役立ちます。 .
さらに簡単です。Instruments を使用して割り当てと参照カウントを追跡し、アクティブなプログラム内のいくつかのオブジェクトの参照カウントとコールスタックを分析します。
歴史的/説明的: 使用を意図していないのに、Apple が NSObject プロトコルでこのメソッドを提供するのはなぜですか? Appleのコードは何らかの目的でretainCountに依存していますか? もしそうなら、なぜどこかに隠されていませんか?
主に次の 2 つの理由から、公開されていると考えられます。
1) 管理された環境で適切な参照カウント。アロケーターが使用しても問題ありませretainCount
ん-本当に。これは非常に単純な概念です。が-[NSObject release]
呼び出されると、(オーバーライドされていない限り) ref カウンターが呼び出される可能性があり、retainCount
(dealloc の呼び出し後) が 0 の場合、オブジェクトの割り当てを解除できます。これは、アロケータ レベルでは問題ありません。アロケーターとゾーンは (大部分) 抽象化されているため、通常のクライアントにとっては意味のない結果になります。retainCount
クライアント レベルで が 0 に等しくならない理由、オブジェクトの割り当て解除、割り当て解除シーケンスなどの詳細については、bbum の解説 (下記) を参照してください。
2) カスタム動作を必要とするサブクラスが利用できるようにするため、および他の参照カウント メソッドが公開されているため。場合によっては便利かもしれませんが、通常は間違った理由で使用されます (不滅のシングルトンなど)。独自の参照カウント スキームが必要な場合は、このファミリをオーバーライドする価値があります。
理解を深めるために: オブジェクトの保持カウントがユーザー コードから想定されるものと異なる理由は何ですか? このような違いを引き起こすフレームワーク コードで使用される可能性のある標準的な手順の例を挙げていただけますか? 保持カウントが新しいユーザーが期待するものと常に異なる既知のケースはありますか?
繰り返しますが、カスタム参照カウント スキームと不滅のオブジェクトです。NSCFString
リテラルは後者のカテゴリに分類されます。
NSLog(@"%qu", [@"MyString" retainCount]);
// Logs: 1152921504606846975
保持カウントについて他に言及する価値があると思われるものはありますか?
デバッグ支援としては役に立ちません。リーク分析とゾンビ分析の使い方を学び、それらを頻繁に使用してください。参照カウントを理解した後でさえも。
更新: bbum は最近、retainCount is uselessというタイトルの記事を投稿しました。-retainCount
この記事には、大部分のケースでなぜ が役に立たないかについての徹底的な議論が含まれています。