了解ViewController dealloc进程

时间:2013-05-20 10:17:30

标签: ios objective-c cocoa-touch automatic-ref-counting

我有一个容器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];
}

我的问题的根源是childdealloc块的末尾没有被@autoreleasepool编辑,而是稍后被释放(从它的外观来看)在RunLoop有机会处理未完成事件的内部列表之后):

enter image description here

这通常不会有问题,但是观察上面函数末尾发出的NSNotification的一个对象依赖于之前的child dealloc它会收到通知。

有人可以解释/链接我的一些文档,以帮助我理解为什么child没有立即发布?

或者,如果我对child dealloc的编辑时间没有选择,那么在dealloc之后,有人可以建议一种简洁的方法来延迟我的通知吗?我想我可以在[ChildViewController dealloc]拨打一个电话通知家长其死亡并在那时发出通知,但这是一种相当肮脏的方式......

2 个答案:

答案 0 :(得分:1)

尝试在下一个runloop迭代中发送通知:

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

答案 1 :(得分:0)

代码中的主要问题是autoreleasepool whcih

  

自动释放池块提供了一种可以放弃的机制   对象的所有权,但避免它的可能性   立即解除分配

基本上autoreleasepool将帮助您删除autorelease块中对象的所有权,但会保证它们不会立即释放。

所以你需要做的就是删除autoreleasepool块并让你的代码保持原样并在代码的底部你也可以让孩子成为child = nil这也会帮助你的班级收到通知。

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