3

我有一个容器UIViewController,它在删除它的一个孩子时执行以下操作:

- (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];
}

我的问题的根源是它child没有dealloc在块的末尾被编辑@autoreleasepool,而是稍后发布(在 RunLoop 有机会处理未完成事件的内部列表之后看起来):

在此处输入图像描述

这通常不会成为问题,但是NSNotification在上述函数结束时观察发送的一个对象依赖于在收到通知之前child被ed。dealloc

任何人都可以向我解释/链接到一些文档以帮助我理解为什么child不立即发布吗?

child或者,如果我对何时发布别无选择dealloc,任何人都可以建议一种干净的方式将我的通知延迟到发布时间之后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块并让您的代码保持原样,并且在代码的底部您还可以使孩子为零child = nil,这也将有助于您的班级收到通知。

也不要编写基于在执行代码时某些对象将被释放的事实的代码。SO 不能保证在调用方法后立即释放一个对象。这只是一个不好的做法,如果可以的话,你应该重新考虑你的实现。

于 2013-05-20T10:32:32.660 回答