2011-09-03 21 views
198

私の小さなiPadアプリでは、オブザーバを使用する「スイッチ言語」機能があります。すべてのビューコントローラは、viewDidLoad:の間に自分のオブザーバに登録されます。 カスタムdeallocとARC(Objective-C)

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

ユーザーは、「言語の変更」ボタンを押した

は、新しい言語は、私のモデルに保存され、観察者が通知され、その登録されたオブジェクトに updateUi:セレクターを呼び出します。

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

戻るviewDidLoad:を使用してオブザーバーに登録したときには、viewDidUnload:を使用して登録を解除しました。私は現在initに登録しているので、deallocで登録を解除することは非常に意味があります。

しかし、ここに私の問題があります。私が書くとき:

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

を私はこのエラーを取得する:

​​

私はスーパークラスが適切にクリーンアップを保証するために[super dealloc]を呼び出す必要がありますが、ARCは、私が今こだわっていることを禁止しているので。オブジェクトが死んでいるときに情報を得る別の方法はありますか? (Clang LLVM ARC document, chapter 7.1.2で説明したように)コンパイラはあなたのためにそれを扱う -

+0

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

+0

私は右利きと左利きのオプションに似たものを実装しました。メッセージを必要とする唯一のVCは、現在表示されているものです。他の人は、viewDidLoadまたはviewDidAppearのモデルを見て、インタフェースを変更します。おそらくこのようなものがうまくいくでしょう。 –

+0

@BlazejCzapp彼はUITabBarControllerを使用しているので、UITabBarControllerは常に登録されたコントローラへの参照を保持しているとしましょう(メモリリークが問題になるでしょうか?登録されたコントローラーがいつ割り当てられるのかはわかりません。ありがとう – Objectif

答えて

400

ARCを使用して、あなたは、単に[super dealloc]が明示的に呼び出すことはありません:

側の注意点として
- (void) dealloc 
{ 
    [observer unregisterObject:self]; 
    // [super dealloc]; //(provided by the compiler) 
} 
+2

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

+0

thatsは仕事が欲しい。オブザーバー自身がコントローラーへの参照を保持するためです。それは最初に呼び出されることのdeallocを防ぐでしょう – hasan83