ARCガイド1-strongおよびweakポインタ

4721 ワード

参考文献:iOS ARC完全ガイド
ヒント:本明細書で説明する「インスタンス変数」は「メンバー変数」、「ローカル変数」は「ローカル変数」です.
一、紹介
ARCはiOS 5以降に追加された新しい特性で、メモリを手動で管理する煩わしさを完全に解消し、コンパイラは適切な場所に適切なretain、release、autorelease文を自動的に挿入します.コンパイラがすべてを処理したので、メモリ管理を心配する必要はありません.
注意:ARCはiOSランタイムプロパティ(weakポインタシステムを除く)ではなく、コンパイラプロパティであり、他の言語のゴミ収集器に似ていません.したがって、ARCは手動メモリ管理と同様にパフォーマンスが向上し、コンパイラがいくつかの最適化を実行できるため、より高速になる場合があります.
二、原理
ARCのルールは非常に簡単です.もう一つの変数がオブジェクトを指す限り、オブジェクトはメモリに保持されます.ポインタが新しい値を指すか、ポインタが存在しない場合、関連するオブジェクトは自動的に解放されます.このルールは、インスタンス変数、synthesizeプロパティ、ローカル変数に適用されます.
三、strongポインタ
コントローラにテキスト入力ボックスのプロパティがあります
@property (nonatomic, assign) IBOutlet UITextField *nameField;

1.ユーザーがテキストボックスにmjという文字列を入力した場合
すなわち、nameFieldのtext属性は、テキスト入力ボックスの内容を保存したNSStringオブジェクトのポインタ、すなわち所有者である
2.次のコードが実行された場合
NSString *name = self.nameField.text;
1つのオブジェクトに複数の所有者を持つことができます.上記のコードでは、name変数もこのNSStringオブジェクトの所有者であり、つまり2つのポインタが同じオブジェクトを指しています.
3.その後、ユーザは、例えば入力ボックスの内容を変更する
このときnameFeildのtext属性は新しいNSStringオブジェクトを指します.ただし、元のNSStringオブジェクトにはまだ所有者(name変数)が存在するため、メモリに保持されます.
4.name変数が新しい値を取得した場合、または存在しなくなった場合(ローカル変数メソッドが返された場合、インスタンス変数オブジェクトが解放された場合など)、元のNSStringオブジェクトは所有者を持たなくなり、retainカウントが0に下がった場合、オブジェクトは解放されます.
例えば、name変数に新しい値を与える
name = @"Jake";

私たちはnameとnameFieldと呼んでいます.textポインタは、オブジェクトの生命を維持できるため、Strongポインタです.デフォルトのすべてのインスタンス変数とローカル変数はStrongポインタです.
四、weakポインタ
Weak型のポインタ変数は、オブジェクトを指すことができますが、オブジェクトの所有者ではありません.
1.次のコードを実行
__weak NSString *name = self.nameField.text;

name変数とnameField.textプロパティは同じNSStringオブジェクトを指しますが、nameは所有者ではありません.
2.テキストボックスの内容が変更されると、元のNSStringオブジェクトに所有者がいなくなり、解放されます.このとき、name変数は自動的にnilになり、空のポインタと呼ばれます.
Weak型のポインタ変数が自動的にnilになるのは便利で、weakポインタが解放されたオブジェクトを指し続けることを阻止し、野ポインタの発生を回避します.そうしないと、非常に探しにくいBugを招き、空のポインタは類似の問題を解消します.
3.weakポインタは主に「父-子」関係に用いられ、父は息子のstrongポインタを持っているため、父は息子の所有者である.しかし、所有権の循環を阻止するために、息子はweakポインタを使って父を指さす必要がある.典型的な例はdelegateモードで、あなたのViewControllerはstrongポインタ(self.view)を通じてUITableViewを持っていて、UITableViewのdataSourceとdelegateはすべてweakポインタで、あなたのViewControllerを指しています
五、strongとweakポインタの使用注意
1.次のコードに問題があります.
__weak NSString *str = [[NSString alloc] initWithFormat:@"1234"];
NSLog(@"%@", str); //  "(null)"

strはweakポインタなので、NSStringオブジェクトには所有者がなく、作成後すぐに解放されます.Xcodeは警告もします(「Warning:Assigning retained object to weak variable;object will be released after assignment」)
2.一般的なポインタ変数はデフォルトでstrongタイプなので、一般的にstrong変数には__を付けません.strong修飾、以下の2行のコードは等価です.
NSString *name = self.nameField.text;
__strong NSString *name = self.nameField.text;

3.属性はstrongまたはweakで、以下のように書くことができます.
@property (nonatomic, strong) NSString *name;
@property (nonatomic, weak) id delegate;

4.
以下のコードは、手動メモリ管理でNSArrayからオブジェクトを削除すると、そのオブジェクトにreleaseメッセージが送信され、すぐに解放される可能性があるため、ARCの前では実行できません.その後NSLog()がそのオブジェクトを印刷するとアプリケーションがクラッシュする
id obj = [array objectAtIndex:0];
[array removeObjectAtIndex:0];
NSLog(@"%@", obj);

ARCではこのコードは完全に合法的です.obj変数はstrongポインタであり、オブジェクトの所有者となり、NSArrayからオブジェクトを削除してもオブジェクトが解放されません.
六、ARCまとめ
1.ARCがあれば、私たちのコードははっきりしていて、いつretainやreleaseオブジェクトを考慮する必要はありません.唯一考慮しなければならないのは、オブジェクト間の関連付けです.つまり、どのオブジェクトがどのオブジェクトを持っているかです.
2.ARCにもいくつかの制限があります.
1>まずARCはObjective-Cオブジェクトでのみ動作します.アプリケーションがCore Foundationまたはmalloc()/free()を使用している場合は、メモリを手動で管理する必要があります.
2>ARCには、ARCが正常に動作することを保証するために、より厳しい言語ルールがあります.
3.ARCはretainとreleaseを管理していますが、メモリ管理の問題に全く関心を持つ必要はありません.strongポインタはオブジェクトの生命を維持するため、これらのポインタをnilに手動で設定する必要がある場合があります.そうしないと、アプリケーションのメモリが不足する可能性があります.新しいオブジェクトを作成するときは、誰がそのオブジェクトを所有するか、そのオブジェクトがどのくらい生き残る必要があるかを考慮する必要があります.
4.ARCはC++とよく組み合わせて使用することができ、ゲーム開発に非常に役立ちます.iOS 4の場合、ARCには少し制限があります(weakポインタはサポートされていません)が、あまり関係ありません
七、ARC使用注意まとめ
1.deallocメソッドを直接呼び出すことはできません.retain,release,autorelease,retainCountメソッドを呼び出すことはできません.@selector(retain)を含むメソッドもできません.
2.deallocメソッドでリソースを管理できますが、インスタンス変数を解放したり、deallocメソッドから[super dealloc]メソッドを削除したりすることはできません.ARCの下で親のdeallocもコンパイラによって自動的に完了します.
3.Core Foundationタイプのオブジェクトは、CFReatin、CFReaseなどの方法で使用できます.
4.NSAllocateObjectおよびNSDellocateObjectオブジェクトは使用できません
5.C構造体でオブジェクトポインタを使用することはできません.このような機能があれば、Objective-Cクラスを作成してこれらのオブジェクトを管理できます.
6.idとvoid*の間に簡便な変換方法はなく、同様にObjective-CとCore Foundationタイプの間の変換にはコンパイラで作成した変換関数が必要である
7.NSAutoreleasePoolオブジェクトは使用できません.ARCは@autoreleasepoolブロックを提供し、より効率的です.
8.メモリメモリ領域を使用できない(NSZoneは使用できない)
9.newを先頭に属性の名前を付けることはできません
10.IBOutletを宣言するときは、StoryBoardのようなnibの中間の最上位オブジェクトにstrongを使用する以外は、weakを使用するのが一般的です.
11.weakは古いバージョンのassignに相当し、strongはretainに相当する.