3

UIViewController子の1つを削除するときに次のことを行うコンテナがあります:

- (void)removeChildWithIndex:(NSUInteger)Index {
  @autoreleasepool {
    ChildViewController *child = [_children objectAtIndex:Index];

    //Remove the child from the VC hierarchy
    [child willMoveToParentViewController:nil];
    [child.view removeFromSuperview];
    [child removeFromParentViewController];

    //Remove the child from array
    [_children removeObjectAtIndex:Index];
  }

  //Post a notification for anyone who might care
  [[NSNotificationCenter defaultCenter] postNotificationName:RemovedChildNotification object:self];
}

私の問題の根本は、ブロックの最後に ed されてchildいないことですが、代わりに少し後で解放されます (RunLoop が未解決のイベントの内部リストを処理する機会を持った後の外観による):dealloc@autoreleasepool

ここに画像の説明を入力

これは通常は問題にはなりませんが、上記の関数の最後で送信されたことを監視している 1 つのオブジェクトは、通知を受信する前に ed に依存NSNotificationしています。childdealloc

childすぐにリリースされない理由を理解するのに役立つドキュメントを説明/リンクしてもらえますか?

または、いつ編集するかについて選択の余地がない場合、誰かchilddealloc私の通知を後まで遅らせるクリーンな方法を提案できdeallocますか? 親にその終焉を知らせるために電話をかけ、[ChildViewController dealloc]その時点で通知を発射することができると思いますが、それはかなり汚い方法です...

4

2 に答える 2

2

次のランループ反復で通知を送信してみてください。

- (void)removeChildWithIndex:(NSUInteger)Index 
{
    ChildViewController *child = [_children objectAtIndex:Index];

    //Remove the child from the VC hierarchy
    [child willMoveToParentViewController:nil];
    [child.view removeFromSuperview];
    [child removeFromParentViewController];
    [child didMoveToParentViewController:nil];

    //Remove the child from array
    [_children removeObjectAtIndex:Index];

    //Post a notification for anyone who might care
    [self performSelector:@selector(_postRemoveChildNotification) withObject:nil afterDelay:0.0f];
}

- (void)_postRemoveChildNotification 
{
    [[NSNotificationCenter defaultCenter] postNotificationName:RemovedChildNotification object:self];
}
于 2013-05-20T11:44:41.653 に答える
0

あなたのコードの主な問題はautoreleasepool

自動解放プール ブロックは、オブジェクトの所有権を放棄できるメカニズムを提供しますが、すぐに割り当てが解除される可能性を回避します。

したがって、基本的にはautoreleasepool、自動解放ブロック内のオブジェクトの所有権を削除するのに役立ちますが、すぐには解放されないことが保証されます。

したがって、autoreleasepoolブロックを削除してコードをそのままにし、コードの下部で子を nil にすることもできchild = nilます。これは、通知を受け取るクラスにも役立ちます。

また、コードの実行時に一部のオブジェクトの割り当てが解除されるという事実に基づくコードを記述しないでください。SO は、メソッドが呼び出された直後に 1 つのオブジェクトの割り当てが解除されることを保証できません。これは単なる悪い習慣です。可能であれば、実装を再考する必要があります。

于 2013-05-20T10:32:32.660 に答える