カスタムの割り当て解除とARC(Objective-C)


208

私の小さなiPadアプリには、オブザーバーを使用する「言語切り替え」機能があります。すべてのView Controllerは、その実行中に自分自身をオブザーバーに登録しviewDidLoad:ます。

- (void)viewDidLoad
{
    [super viewDidLoad];
    [observer registerObject:self];
}

ユーザーが[言語を変更]ボタンを押すと、新しい言語がモデルに保存され、オブザーバーに通知さupdateUi:れ、登録されたオブジェクトのセレクターを呼び出します。

これは、TabBarControllerにビューコントローラーがある場合を除いて、非常にうまく機能します。これは、タブバーが読み込まviewDidLoad:れると、ビューを初期化せずに子コントローラーからタブアイコンをフェッチするため、呼び出されないため、これらのビューコントローラーは言語変更通知を受信しないためです。このため、registerObject:呼び出しをinitメソッドに移動しました。

以前viewDidLoad:はオブザーバーに登録していたとき、以前viewDidUnload:は登録解除していました。現在で登録しているのでinit、で登録を解除することは非常に理にかなっていdeallocます。

しかし、これが私の問題です。私が書くとき:

- (void) dealloc
{
    [observer unregisterObject:self];
    [super dealloc];
}

私はこのエラーを受け取ります:

ARCは「dealloc」の明示的なメッセージ送信を禁止します

[super dealloc]スーパークラスが適切にクリーンアップされるように呼び出す必要があるので、ARCはそれを禁止しているので、今は行き詰まっています。オブジェクトが死んでいるときに通知を受ける別の方法はありますか?


補足として-このような状況はメモリリークを引き起こす可能性があり、リークツールでは表示されません。dataModelがオブザーバーへの参照を保持している場合(これは、ARCではivarの場合でもデフォルトです)、保持カウントがゼロより大きいため、deallocが呼び出されることはありません。したがって、最初にdeallocを呼び出せるようにするには、オブザーバーを手動で登録解除する必要がある場合があります。
BłażejCzapp

右利きオプションと左利きオプションに同じようなものを実装しました。メッセージを必要とする唯一のVCは、現在表示されているVCです。他のユーザーは、viewDidLoadまたはviewDidAppearでモデルを見て、インターフェースに変更を加えます。たぶん、このようなものがうまくいくでしょう。
Doug Watkins

@BlazejCzappはUITabBarControllerを使用しているため、UITabBarControllerは常に登録されたコントローラーへの参照を保持するとします(「子」コントローラーの場合がそうです)、メモリリークは引き続き問題になりますか?登録されたコントローラーがいつ割り当てられるかわかりません。ありがとう
Objectif 2016年

回答:


419

ARCを使用する場合は、[super dealloc]明示的に呼び出すのではなく、コンパイラが処理します(Clang LLVM ARCドキュメントの7.1.2章で説明されています)。

- (void) dealloc
{
    [observer unregisterObject:self];
    // [super dealloc]; //(provided by the compiler)
}

4
ビューがオブザーバーへの参照を保持し、オブザーバーがビューへの参照を保持している場合、循環参照があります。したがって、ビューの参照カウントは0より大きく、dealloc呼び出されることはありません。[observer unregisterObject:self]dealloc を呼び出すことは意味がありますか?何が欠けていますか?
user443854 2015

それは仕事が欲しい。オブザーバー自体がコントローラーへの参照を保持しているためです。そもそも呼び出されたdeallocを防ぐ
hasan
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.