
私たち
が取り組んでいるプロジェクトの中には、おそらく、すべてが記憶とともに整然と並んでいるものはありません。 この投稿では、この種の問題に対処する方法の話に専念します。
メモリの問題には、リークやいわゆる「ゾンビ」が含まれます。 混乱したメモリが作成されるアプリケーションは不安定になり、いくつかのインターフェイス要素の消失から始まりクラッシュで終わる奇妙なものがたくさん現れます。
まず、リークとは何かを判断しましょう。 リーク-割り当てられているが、ポインタがないメモリ領域が解放されていない。 これはかなり軽薄に見え、iPhoneには大量のRAMがあり、通常のアプリケーションはせいぜい2 MBしか占有しません。 実際、すべてがそれほどバラ色ではありません。アプリケーションは最大3 MBを使用でき、メモリ警告がそれぞれ表示されるようになり、OSは「不要」と見なされる領域を解放しようとしています。 簡単に言えば、現在見えないインターフェース要素を削除します。これは見苦しいだけでなく、アプリケーションのクラッシュを引き起こす可能性もあります。 「ゾンビ」は、プログラムがアクセスしようとしているメモリの領域をすでに解放(キル)しているため、アプリケーションのクラッシュにつながります。
IOSにはガベージコレクターがあります!
多くの人(はい、私自身がこれを罪にしています)はしばしばそれが存在しないと言います。 しかし、非常に原始的ではありますが、ガベージコレクターはまだあります。 メモリ管理の原則は、オブジェクトへのリンクの数をカウントすることに基づいています。 オブジェクトにメモリを割り当てると、その数は1に設定され、0に達するとメモリが解放されます(ガベージはスローされます)。 オブジェクトを使用するたびに、リンクの数を増やす必要があり、不要になるたびに減らす必要があります。
4つの魔法の言葉があります
メモリーを管理するには、
alloc 、
copy 、
retain 、
release 4つの単語だけを覚える必要があります。 それぞれについて個別に話しましょう。
allocオブジェクトにメモリを割り当て、リンクの数を1つ増やします。新しいオブジェクトを作成するたびにリンクを使用する必要があります。
copyオブジェクト(ポインターではない)をコピーします。 コピーしているオブジェクトへの参照の数は変更せず、新しいオブジェクトへの参照の数を増やします。
retainオブジェクトへの参照の数を増やすだけです。
release上記の3つの操作の逆は、リンクの数を1つ減らします。
そして何か他のもの
Autoreleaseこれは少し異なる話です。 オブジェクトに
autoreleaseメッセージを送信すると、「遅延」
releaseが発生します。 これは、何らかの理由でアクションを実行した後にオブジェクトに
releaseするメッセージを送信できない場合に必要です。 その主な用途は、メソッドによるオブジェクトの戻りです。 名前に
alloc 、
copy 、
retainを持たないメソッドは、「承認」オブジェクトを返します。
しかし、それをどこでも使用してみませんか? これはとても便利です! 便利ですが、高価です。 オブジェクトへの参照の数がそれぞれすぐに減少しないという事実により、メモリもすぐには解放されません。 ここには落とし穴があります。3MBしかないため、一度に大量のデータを処理すると、まったく同じメモリ警告が表示されます。
Deallocこのメソッドは、オブジェクトが削除されたときに呼び出され、オブジェクトが使用したすべての変数を解放し、最後に親で
deallocを呼び出す
deallocがあります。
- (void)dealloc {
[model release];
[view release];
[super dealloc];
}
Propertyプロパティに
retain 、
assign 、
retain 、
copy 3つのタイプがあり
copy 。 最後の2つはすでに明確になっているはずです。 そして最初のものは、オブジェクトへの参照の数に影響を与えることなく、単に値を割り当てます。 タイプごとにセッターの正しい実装を提供します。
//assign
- (void)setList:(List *)list{
_list = list;
}
//retain
- (void)setList:(List *)list{
[_list autorelease];
_list = [list retain];
}
//copy
- (void)setList:(List *)list{
[_list autorelease];
_list = [list copy];
}
Property動作を監視する必要はなく、設定するだけで、必要に応じて値をリセットし、リセットするだけです。
デリゲート、チキン、エッグ
その過程で、大量のオブジェクトがリークしているという事実に関連する問題に遭遇しました。 相互に保持する2つのオブジェクトがあり、したがってメモリを解放しないことが判明しました。 これは、委任パターンを使用しているときに起こりました。 別のオブジェクトを作成し、それ自体をデリゲートにするオブジェクトがありました。 そして、
Delegateプロパティは
retainとして登録されました。
retainを
assign置き換えることにより、状況が保存されます。
最後のいくつかのヒント
- リリースという単語は、
alloc 、 retainまたはcopy直後に来る必要がありcopy - そして、
release直後の単語nil - 常にnilデリゲートについて
- 可能であれば、
autorelease控えます - 必要なときにオブジェクトを作成する
- クラスフィールドを乱用しないでください
- Static Analysys Toolはすべてを美しく明確に描画します
- 漏れがないか時々確認してください
Ivan Ushakov、iOSチームプログラマー