【发布时间】:2013-05-14 21:07:59
【问题描述】:
我有一个容器 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 不是在@autoreleasepool 块的末尾被dealloced,而是稍后发布(在 RunLoop 有机会之后看起来处理未完成事件的内部列表):
这通常不会成为问题,但是观察在上述函数末尾发出的NSNotification 的一个对象在收到通知之前依赖child 是dealloced。
谁能解释/链接到一些文档来帮助我理解为什么child 没有立即发布?
或者,如果我别无选择child 何时是dealloced,任何人都可以建议一种干净的方法将我的通知延迟到dealloc 之后?我想我可以拨打[ChildViewController dealloc] 通知父母它的死亡并在那时发出通知,但这是一种非常肮脏的方式......
【问题讨论】:
-
willMoveToParentViewController不是委托方法吗?你为什么要明确地称呼它?你为什么使用@autoreleasepool;我没有看到任何正在创建的自动释放对象?我认为最好的解决方法是删除“依赖于被释放的孩子”的要求。 -
观察者真的依赖被释放的孩子吗?而不是依赖它不再有父母?
-
@trojanfoe: This is explained in the docs,但我仍然觉得它非常不直观:添加 VC 时,
willMove...被称为隐式,didMove...必须被称为显式。删除时情况正好相反。 -
您对
willMoveToParentViewController的看法是正确的,这对我来说似乎也违反直觉。我喜欢@danypata 建议的在调用通知之前设置child=nil的想法,但是我仍然觉得真正的解决方案在于围绕观察者中的“依赖于被释放的孩子”要求进行编码。如果不是nil,为什么不在孩子身上设置一个说“我死了”的标志。 -
当然有道理。不测试
dealloced而是使用私有标志或测试其层次结构而不是将子级与其父级分离的想法怎么样?
标签: ios objective-c cocoa-touch automatic-ref-counting