私の小さな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で説明したように)コンパイラはあなたのためにそれを扱う -
- このような状況は、メモリリークを引き起こす可能性があり、リークツールには表示されません。 dataModelがオブザーバへの参照を保持している場合(これはivarsの場合でもARCでのデフォルトのものです)、保持カウントがゼロよりも大きいため、deallocは呼び出されません。したがって、最初にdeallocを呼び出すことができるように、オブザーバを手動で登録解除する必要があります。 –
私は右利きと左利きのオプションに似たものを実装しました。メッセージを必要とする唯一のVCは、現在表示されているものです。他の人は、viewDidLoadまたはviewDidAppearのモデルを見て、インタフェースを変更します。おそらくこのようなものがうまくいくでしょう。 –
@BlazejCzapp彼はUITabBarControllerを使用しているので、UITabBarControllerは常に登録されたコントローラへの参照を保持しているとしましょう(メモリリークが問題になるでしょうか?登録されたコントローラーがいつ割り当てられるのかはわかりません。ありがとう – Objectif