8

ビューコントローラーのメソッドで-addObserverForName: object: queue: usingBlock:forを使用すると、メソッドが呼び出されなくなります。 NSNotificationCenter-viewDidLoad:-dealloc

( を削除する-addObserverForName: object: queue: usingBlock:と、-deallocが再度呼び出されます。)

使用-addObserver: selector: name: object:してもこの問題はないようです。私は何を間違っていますか?(私のプロジェクトは ARC を使用しています。)

ここで何か間違ったことをしている場合に備えて、以下は私の実装の例です。

[[NSNotificationCenter defaultCenter] addObserverForName:@"Update result"
                                                  object:nil
                                                   queue:nil
                                              usingBlock:^(NSNotification *note) {
                                                  updateResult = YES;
                                              }];

助けてくれてありがとう。

私は以下を追加しようとしました(無駄に):

- (void)viewWillDisappear:(BOOL)animated
{
    [super viewWillDisappear:animated];

    if ([self isMovingFromParentViewController]) {
        [[NSNotificationCenter defaultCenter] removeObserver:self];
    }
}
4

3 に答える 3

17

updateResultオブジェクトがそのブロックによって保持されるため、オブジェクトの割り当てが解除されるのを防ぐインスタンス変数です。

言い換えれば、保持サイクルを取得しました。オブジェクトはブロックを保持し、ブロックはオブジェクトを保持します。

その関係を失うには、そのインスタンスとその変数への弱い参照または unsafe_unretained 参照を作成する必要があります。

通知ブロックの前に次を追加します。

__unsafe_unretained YouObjectClass *weakSelf = self;

または(iOS5以降の場合)

__weak YouObjectClass *weakSelf = self;

次に、そのブロック内で、その新しい弱参照を介してオブジェクトを参照します。

[[NSNotificationCenter defaultCenter] addObserverForName:@"Update result"
                                                  object:nil
                                                   queue:nil
                                              usingBlock:^(NSNotification *note) {
                                                  weakSelf.updateResult = YES;
                                              }];

Please note that retain-cycles are not a bad thing per se. Sometimes you actually want them to happen. But those are instances where you are certain that the cycle will be broken after a specific time (e.g. Animation Blocks). The cycle is broken once the block has executed and is removed from the stack.

于 2012-10-02T22:26:30.957 に答える
6

これは、保持サイクルがあるためと考えられます。

これは通常、ブロックが暗黙的に自己を保持し、ある意味で自己がブロックを保持する場合に当てはまります。それぞれがもう一方を保持するため、保持サイクルがあり、したがって、retainCountがゼロに達することはありません。

-Warc-retain-cyclesこのような問題について警告する警告をアクティブにする必要があります。

したがって、あなたの場合、updateResultインスタンス変数であると私が想定している変数を使用しており、これは暗黙的にを保持しselfます。代わりに、一時的な弱い変数を使用して自己を表し、これをブロックで使用して、保持されないようにし、保持サイクルを中断する必要があります。

__block __weak typeof(self) weakSelf = self; // weak reference to self, unretained by the block
[[NSNotificationCenter defaultCenter] addObserverForName:@"Update result"
                                              object:nil
                                               queue:nil
                                          usingBlock:^(NSNotification *note) {
                                              // Use weakSelf explicitly to avoid the implicit usage of self and thus the retain cycle
                                              weakSelf->updateResult = YES;
                                          }];
于 2012-10-02T22:29:06.967 に答える