ARCを使用する場合、deallocでプロパティをnilに設定しますか?


125

私はiOS 5で自動参照カウントを学習しようとしています。これで、この質問の最初の部分は簡単になるはずです。

  1. ARCを使用するときに、deallocに明示的なrelease-propertyステートメントを記述する必要がないことは正しいですか?言い換えれば、以下は明示的な割り当て解除を必要としないというのは本当ですか?

    @interface MyClass : NSObject
    @property (strong, nonatomic) NSObject* myProperty;
    @end
    
    @implementation MyClass
    @synthesize myProperty;
    @end
    
  2. 次に重要な質問は、ARCへの移行に関するリリースノートドキュメントの次の行にあります。

    インスタンス変数を解放する必要はありません(実際に解放することはできません)が、ARCを使用してコンパイルされていないシステムクラスやその他のコードで[self setDelegate:nil]を呼び出す必要がある場合があります。

    これは疑問を投げかけます:どのシステムクラスがARCでコンパイルされていないかをどうやって知るのですか?独自のdeallocを作成し、強く保持するプロパティを明示的にnilに設定する必要があるのはいつですか?プロパティで使用されるすべてのNSおよびUIフレームワーククラスが明示的な割り当て解除を必要とすると想定する必要がありますか?

SOやその他の場所では、手動参照追跡を使用するときにプロパティのバッキングivarを解放する方法について豊富な情報がありますが、ARCを使用するときの情報は比較的少ないです。

回答:


197

短い答え:いいえ、deallocARCでプロパティをnilする必要はありません。

長い答えdealloc手動のメモリ管理であっても、でプロパティを無効にすることはできません。

MRRでは、ivarsを解放する必要があります。プロパティを無効にすることは、セッターを呼び出すことを意味します。セッターを呼び出す必要がないコードを呼び出す可能性がありますdealloc(たとえば、クラスまたはサブクラスがセッターをオーバーライドする場合)。同様に、KVO通知をトリガーする可能性があります。代わりにivarを解放すると、これらの望ましくない動作が回避されます。

ARCでは、システムがivarを自動的に解放するため、それがすべての場合、実装する必要はありませんdealloc。ただし、特別な処理が必要な非オブジェクトivar(たとえば、必要な割り当て済みバッファーfree())がある場合でも、でそれらを処理する必要がありますdealloc

さらに、自分をオブジェクトのデリゲートとして設定した場合deallocは、その関係の設定を解除する必要があります(これはの呼び出しについてのビットです[obj setDelegate:nil])。ARCでコンパイルされていないクラスでこれを行うことについての注意は、弱いプロパティにうなずくことです。クラスが明示的にそのdelegateプロパティをマークしている場合、weakこれを行う必要はありません。弱いプロパティの性質は、それがあなたのためにnilledされることを意味するからです。ただし、プロパティがマークassignされているdealloc場合は、でそれをnilする必要があります。そうでない場合、クラスにはぶら下がりポインタが残され、デリゲートにメッセージを送ろうとするとクラッシュする可能性があります。これは、デリゲートなどの保持されない関係にのみ適用されることに注意してください。


2
意味あり!これについてお聞きします。私が持っている一般的なシナリオMyController : UIViewControllerは、UIViewを作成および所有し、ビューのデリゲートをそれ自体に設定するクラスがあるというものです。それはその見解の唯一の保持所有者です。コントローラが割り当て解除されると、ビューも割り当て解除されます。デリゲートポインターがぶら下がっているかどうかは重要ですか?
翌年

4
@emfurry:おそらくそうではありません。なぜなら、ビューコントローラーが終了するときまでに、ビュー自体はビュー階層に存在していてはならず、何も実行していないはずですが、想定を行わないことが最善です。ビューが非同期でスケジュールされた作業を後で実行するようにスケジュールし、ビュー自体が最終的にビューコントローラーより短い時間で終了する場合(たとえば、非同期作業が一時的にビューを保持するため)。安全のためにデリゲートを無視するのが最善です。そして実際、問題のビューがであるUIWebView場合、ドキュメントはデリゲートを無視する必要があることを明示的に述べています。
リリーバラード

3
@zeiteisen:いいえ。プロパティとunsafe_unretainedまったく同じであり、assignMRRの下での委任関係の通常の動作であり、これらを取り除く必要があります。
Lily Ballard、

4
MRCのdeallocでセッターを使用しないことについての意見に同意しません。Appleはそれを推奨していませんが、コードでもそれを行っています。セッターを使用しないことで、実際に新しい問題を作成できます。それについていくつかの大きな議論があります。重要なのは、setterを正しく記述し(nil値を渡した場合は正しく動作する必要がある)、割り当て解除の順序を監視することです。
スルタン

7
@Sulthan:deallocでセッターを使用するかどうかは膨大な量のワームですが、私の立場は基本的に次のようになります。deallocで可能な限り小さなコードを呼び出す必要があります。セッターは、サブクラスでオーバーライドするか、KVOまたはその他のメカニズムを介して、副作用を含む傾向があります。deallocの副作用は、ペストのように特に回避する必要があります。deallocからメソッド呼び出しを削除できる場合は、削除する必要があります。これは次のように簡略化されています。deallocでセッターを呼び出さないでください。
Lily Ballard、

2

反対の答えを出すためだけに...

短い答え:いいえ、deallocARC で自動合成されたプロパティをnilする必要はありません。また、のセッターを使用する必要はありませんinit

長い答え:ARCでも、でカスタム合成されたプロパティを削除する必要がありdeallocます。そして、のセッターを使用する必要がありますinit

重要なのは、カスタム合成されたプロパティは、無効化に関して安全かつ対称的である必要があるということです。

タイマーの可能なセッター:

-(void)setTimer:(NSTimer *)timer
{
    if (timer == _timer)
        return;

    [timer retain];
    [_timer invalidate];
    [_timer release];
    _timer = timer;
    [_timer fire];
}

scrollview、tableview、webview、textfield、...の可能なセッター:

-(void)setScrollView:(UIScrollView *)scrollView
{
    if (scrollView == _scrollView)
        return;

    [scrollView retain];
    [_scrollView setDelegate:nil];
    [_scrollView release];
    _scrollView = scrollView;
    [_scrollView setDelegate:self];
}

KVOプロパティの可能なセッター:

-(void)setButton:(UIButton *)button
{
    if (button == _button)
        return;

    [button retain];
    [_button removeObserver:self forKeyPath:@"tintColor"];
    [_button release];
    _button = button;
    [_button addObserver:self forKeyPath:@"tintColor" options:(NSKeyValueObservingOptions)0 context:NULL];
}

そして、あなたはのために任意のコードを複製する必要はありませんdeallocdidReceiveMemoryWarningviewDidUnload、...とあなたの財産を安全に公開されてすることができます。でのnil outプロパティについて心配していた場合はdealloc、セッターをもう一度確認するときかもしれません。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.