14

ARC を使用し、iOS 5 以降を対象とする iOS アプリを作成しています。

デリゲート プロパティを持つカスタム ビュー オブジェクトを作成するとします。デリゲート プロパティを宣言する際に、保持サイクルを回避するために弱参照にします。これにより、実際のデリゲート オブジェクト (コントローラー) が破棄されると、次のようにカスタム ビューも破棄されます。

@interface MyCustomView : UIView

@property (nonatomic, weak) id<MyCustomViewDelegate> delegate;

@end

すべてが良いです。

コントローラー オブジェクトを作成しています。このオブジェクトには、カスタム ビューと Apple 提供の UIKit ビューの 2 つのビュー オブジェクトへの参照が含まれています。どちらもデリゲート プロパティを宣言しており、コントローラーは両方のビューのデリゲートです。たぶん、次のようになります。

@interface MyViewController : UIViewController <MyCustomViewDelegate, UITableViewDataSource, UITableViewDelegate>

@property (nonatomic, strong) MyCustomView *customView;
@property (nonatomic, strong) UITableView *tableView;

@end

@implementation MyViewController

- (void)viewDidLoad
{
    self.customView.delegate = self;
    self.tableView.dataSource = self;
    self.tableView.delegate = self;
}

@end

私の質問は次のとおりです。dealloc をオーバーライドして、いずれかまたは両方のデリゲートを nil に設定する必要がありますか?

私が理解しているように、UIKit ビュー (この場合はtableView) のデリゲート プロパティは、実際には弱い参照として宣言されているのではなく、__unsafe_unretained非 ARC バージョンの iOS との下位互換性のために参照として宣言されています。だから多分私は書く必要があります

- (void)dealloc
{
    _tableView.dataSource = nil;
    _tableView.delegate = nil;
}

今、dealloc をオーバーライドする必要がある場合でも、設定する必要はありません_customView.delegate = nilよね? それは(私によって)弱い参照であると宣言されたため、 の破棄時に自動的に nil に設定する必要がありMyViewControllerます。

しかし一方で、私は非 ARC バージョンの iOS を対象としているわけではなく、そうするつもりもありません。たぶん、dealloc をオーバーライドする必要はまったくないのでしょうか?

4

3 に答える 3

30

弱くないデリゲートを nil に設定することは、その必要がないことがわかっている場合を除き、一般的には良い考えです。UITableViewとについてUIScrollViewは、次の手順で以前の iOS バージョンでクラッシュを経験しました (ゾンビを有効にして実行すると役立つ場合があります)。

  1. 本当に速くスクロールします。
  2. [完了] または [戻る] ボタンなどを押して、VC を閉じます。

これは、スクロール アニメーションがビューへの参照を保持しているために発生しているように見えるため、ビューは VC より長く存続します。スクロール イベントを送信するとクラッシュします。

リクエストが読み込まれているUIWebView間、単にデリゲートを nil に設定するだけでは十分ではなかった (回避策は を呼び出すことだったと思います[webView loadRequest:nil])。

于 2013-02-22T04:06:22.783 に答える
2

said への唯一の強力な参照がtableView唯一のコントローラーである場合は、手動でorをMyViewController設定する必要はありません。UITableViewDelegateUITableViewDataSourcenil

その理由は、deallocメソッドが呼び出されると、テーブルビューもコントローラーと共に破棄されるためです (つまり、それへの唯一の参照が唯一のコントローラークラスである限り) MyViewControllerMyViewController

MyViewController他のコントローラーなど、このテーブルビューへの他の強い参照がある場合、テーブルビューがクラスよりも長く存在する可能性があります。このような場合、の dealloc メソッドでandを設定する必要があります。これは、前述のように、これらのプロパティは弱参照ではなく、自動的に に設定されないためです。UITableViewDelegateUITableViewDataSourcenilMyViewControllernil

ただし、この種の状況は私の経験ではかなりまれです。

ほとんどの場合、これらを正直に設定することについて心配することはありませんnilが、これは防御的なプログラミング手法です。

この投稿も参照してください。

dealloc メソッドでは、nil へのデリゲートが必要か不要かを設定します

于 2013-02-22T03:41:57.987 に答える
0

delegateanddataSourceを明示的に設定する唯一の理由nilは、customViewまたはtableViewが View Controller を使用できない場合です。それらを に設定すると、割り当てが解除されたオブジェクトを参照したり参照したりするnilのを防ぐことができます。delegatedataSource

andがView Controllerとともに割り当て解除される場合、customViewandを nil アウトする必要はありません。tableViewdelegatedataSource

于 2013-02-22T03:37:58.547 に答える