メモリの問題には、リークやいわゆる「ゾンビ」が含まれます。 混乱したメモリが作成されるアプリケーションは不安定になり、いくつかのインターフェイス要素の消失から始まりクラッシュで終わる奇妙なものがたくさん現れます。
まず、リークとは何かを判断しましょう。 リーク-割り当てられているが、ポインタがないメモリ領域が解放されていない。 これはかなり軽薄に見え、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チームプログラマー