web-dev-qa-db-ja.com

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

IOS 5で自動参照カウントを学習しようとしています。この質問の最初の部分は簡単です。

  1. [〜#〜] not [〜#〜]ARCを使用するときにdeallocに明示的なrelease-propertyステートメントを記述する必要はありますか?言い換えれば、以下は[〜#〜] not [〜#〜]が明示的にdeallocを必要とするのは本当ですか?

    @interface MyClass : NSObject
    @property (strong, nonatomic) NSObject* myProperty;
    @end
    
    @implementation MyClass
    @synthesize myProperty;
    @end
    
  2. 次のより重要な質問は、 Transitioning to ARC Release Notes documentの行から来ています。

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

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

手動参照追跡を使用する場合のプロパティのバッキングivarのリリースのプラクティスに関するSOおよびその他の場所には豊富な情報がありますが、ARCを使用する場合はこれに関する情報は比較的少ないです。

123
emfurry

簡単な答え:いいえ、ARCの下のdeallocのプロパティを削除する必要はありません。

ロングアンサー:手動のメモリ管理であっても、deallocのプロパティをゼロにしないでください。

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

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

さらに、自分をオブジェクトのデリゲートとして設定した場合は、deallocでその関係を設定解除する必要があります(これは[obj setDelegate:nil])。 ARCでコンパイルされていないクラスでこれを行うことについての注意は、弱いプロパティに向かってうなずきます。クラスがそのdelegateプロパティをweakとして明示的にマークしている場合、これを行う必要はありません。弱いプロパティの性質により、それは自動的に削除されます。ただし、プロパティにassignのマークが付いている場合は、deallocでそれを破棄する必要があります。これは、デリゲートなどの保持されない関係にのみ適用されることに注意してください。

197
Lily Ballard

ちょうど反対の答えを与えるために...

短い答え:いいえ、ARCの下のdeallocにある自動合成プロパティを削除する必要はありません。また、initのセッターを使用する必要はありません。

ロングアンサー:あなたshouldARCの下であっても、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、...のコードを複製する必要がなくなり、プロパティを安全に公開できます。 deallocのプロパティがゼロになることが心配な場合は、セッターを再度チェックするときが来るかもしれません。

1
Cœur