mik*_*dev 14 uiviewcontroller ios automatic-ref-counting
我有一个自定义容器UIViewController,它有六个子UIViewControllers,以及一组用户与之交互以在子视图控制器之间切换的选项卡.问题是当我的容器视图控制器被释放时,子视图控制器不是.
我已经验证通过向dealloc方法添加一些调试代码而不释放子视图控制器,只要它们的视图没有添加到容器视图控制器的视图中,它们就会被释放.
下面是我用来创建自定义容器视图控制器的代码的摘录.viewController指针是iVars.我也在使用ARC,这就是为什么没有实际的发布调用.
- (void)init
{
if ((self = [super init])) {
vc1 = [[UIViewController alloc] init];
[self addChildViewController:vc1];
vc2 = [[UIViewController alloc] init];
[self addChildViewController:vc2];
vc3 = [[UIViewController alloc] init];
[self addChildViewController:vc3];
vc4 = [[UIViewController alloc] init];
[self addChildViewController:vc4];
vc5 = [[UIViewController alloc] init];
[self addChildViewController:vc5];
vc6 = [[UIViewController alloc] init];
[self addChildViewController:vc6];
}
return self;
}
- (void)dealloc
{
[vc1 removeFromParentViewController];
vc1 = nil;
[vc2 removeFromParentViewController];
vc2 = nil;
[vc3 removeFromParentViewController];
vc3 = nil;
[vc4 removeFromParentViewController];
vc4 = nil;
[vc5 removeFromParentViewController];
vc5 = nil;
[vc6 removeFromParentViewController];
vc6 = nil;
}
- (void)switchFromViewController:(UIViewController *)fromViewController toViewController:(UIViewController *)toViewController
{
if (fromViewController) {
[fromViewController.view removeFromSuperview];
}
[self.view addSubview:toViewController];
toViewController.view.frame = self.view.bounds;
}
Run Code Online (Sandbox Code Playgroud)
你们有什么想法我做错了吗?
Sri*_*nth 26
这不是添加和删除子视图控制器的方法
[childViewController willMoveToParentViewController:nil];
[childViewController view] removeFromSuperview];
[childViewController removeFromParentViewController];
Run Code Online (Sandbox Code Playgroud)
是删除和添加它的方法
[parentViewController addChildViewController:childViewController];
[parentViewController.view addSubview:childViewController.view];
[childViewController didMoveToParentViewController:parentViewController];
Run Code Online (Sandbox Code Playgroud)
Rob*_*Rob 12
我怀疑,问题与问题中的视图控制器包含代码无关,而是您添加了观察者(您在回答此问题时讨论):
[[NSNotificationCenter defaultCenter] addObserverForName:kUpdateEventName object:nil queue:nil usingBlock:^(NSNotification *note) {
// do stuff when update happen
}];
Run Code Online (Sandbox Code Playgroud)
而你试图删除它
[[NSNotificationCenter defaultCenter] removeObserver:self name:kUpdateEventName object:nil];
Run Code Online (Sandbox Code Playgroud)
所以,有两个问题:
如果使用addObserverForName:object:queue:,这不是删除此观察者的正确方法.相反,定义一个属性来跟踪观察者:
@property (nonatomic, weak) id<NSObject> notification;
Run Code Online (Sandbox Code Playgroud)
然后在创建时保存对该观察者的引用:
self.notification = [[NSNotificationCenter defaultCenter] addObserverForName:kUpdateEventName object:nil queue:nil usingBlock:^(NSNotification *note) {
// do something
}];
Run Code Online (Sandbox Code Playgroud)
如果要删除它,请使用以下参考:
[[NSNotificationCenter defaultCenter] removeObserver:self.notification];
Run Code Online (Sandbox Code Playgroud)
这将确保观察员得到适当的移除.
在此观察者到位时释放子视图控制器失败意味着您传递给的此块addObserverForName:object:queue:必须具有引用self.如果您试图正确删除此观察者(如上所示)dealloc,您仍然会有一个强大的参考周期(以前称为保留周期).这可以通过多种方式解决,但最强大的模式是通过使用weakSelf模式首先防止强引用循环:
typeof(self) __weak weakSelf = self;
self.notification = [[NSNotificationCenter defaultCenter] addObserverForName:kFooNotification object:nil queue:nil usingBlock:^(NSNotification *note) {
// use `weakSelf` in this block; not `self`
}];
Run Code Online (Sandbox Code Playgroud)我原来的答案如下:
虽然Srikanth之后是正确的addChildViewController,你应该打电话didMoveToParentViewController:self,然后removeFromParentViewController再打电话willMoveToParentViewController:nil.但那不是你的问题.事实上,我使用了你的代码的变体(即使没有dealloc),并且子控制器被释放得很好.
最重要的是,我怀疑你的问题在别处,可能是某个地方的保留周期.例如,您的孩子是否有强烈的父母参考?你在使用定期计时器吗?您引用一些选项卡.您没有使用标签栏控制器,是吗?它必须是那样的.
[如果您想查看原始答案的其余部分,请参阅修订历史记录,其中包含代码片段和OP代码示例的次要详细信息]
| 归档时间: |
|
| 查看次数: |
15508 次 |
| 最近记录: |