【问题标题】:removeFromParentViewController - do you need to nil afterwards?removeFromParentViewController - 之后你需要 nil 吗?
【发布时间】:2014-10-12 12:17:26
【问题描述】:

子视图控制器可以“关闭自己”吗? .....


您有一个视图控制器“RedMessage”。你有一个普通的强大属性......

@property (strong) RedMessage *red;

您将它(“模态”)添加到您当前的 VC 之上...

self.red = (RedMessage *)[self.storyboard
     instantiateViewControllerWithIdentifier:@"RedMessageID"];
self.red.view.frame = self.view.frame;
[self.view addSubview:self.red.view];
[self addChildViewController:self.red];
[self.red didMoveToParentViewController:self];

要稍后摆脱它,请执行此操作

[self.red willMoveToParentViewController:nil];
[self.red.view removeFromSuperview];
[self.red removeFromParentViewController];

但事实上,你需要这样做吗??

[rm willMoveToParentViewController:nil];
[rm.view removeFromSuperview];
[rm removeFromParentViewController];
rm = nil;

你需要“= nil;”吗?

请注意,这个问题很关键,因为:如果您不必将其设为 nil,则可以在新视图控制器中执行以下操作...

-(void)dismissMyselfCompletely
    {
    [self willMoveToParentViewController:nil];
    [self.view removeFromSuperview];
    [self removeFromParentViewController];
    }

非常方便。

简而言之,如果您在新的顶视图控制器中执行此操作 - 它会“工作”,是否会释放 VC?

当removeFromParentViewController发生时,父VC是否明白可以释放self.red?

【问题讨论】:

  • 赏金供权威参考。
  • 很抱歉提供自己的答案,但我们确实对其进行了广泛的测试并发现答案中给出的结果......希望它对某人有所帮助!

标签: ios uiviewcontroller


【解决方案1】:

经过大量测试,我们发现情况似乎是这样的:

实际上,您可以允许 VC “删除自身”。

它确实消失了,没有保留。

我们像这样在顶部添加 VC(就像您在顶部添加“模态”VC 的通常方式......)

-(void)showOverlay:(NSDictionary*)dict
    {
    Red *rr = (Red *)[self.storyboard
        instantiateViewControllerWithIdentifier:@"RedID"];
    rr.view.frame = self.view.bounds;
    [self.view addSubview:rr.view];
    [self addChildViewController:rr];
    [rr didMoveToParentViewController:self];
    
    [rr useThisData:dict];
    }

请注意,没有持有 rr 的属性 - 它只是在该类别中动态创建和添加。

在“红色”内部,我们就像这样摆脱它......

-(void)dismiss:(UITapGestureRecognizer *)sender
    {
    [self.view exitLeftSmoothly:0 then:^
        {
        [self willMoveToParentViewController:nil];
        [self.view removeFromSuperview];
        [self removeFromParentViewController];
        }];
    }

(exitLeft只是一个动画,不相关)

最后你可以像这样测试它

-(void)viewDidAppear:(BOOL)animated
    {
    [super viewDidAppear:animated];
    ....
    [self _teste];
    }

-(void)_teste
    {
    Red __weak *mySelf = self;
    dispatch_after_secs_on_main(0.5, ^
        {
        NSLog(@"tick !!!!!!!!!!!!");
        if ( mySelf == nil ) NSLog(@"I no longer exist - WTF!");
        [mySelf _teste];
        });
    }

您可以清楚地看到,一旦“Red” vc 被解除,代码确实停止运行:“Red”已经消失。

它似乎确实可靠地工作。您的输出将如下所示...

2014-10-22 17:26:36.498 [1738:111092] tick --- !!!!!!!!!!!!
2014-10-22 17:26:37.031 [1738:111092] tick --- !!!!!!!!!!!!
2014-10-22 17:26:37.576 [1738:111092] tick --- !!!!!!!!!!!!
2014-10-22 17:26:38.124 [1738:111092] tick --- !!!!!!!!!!!!
2014-10-22 17:26:38.674 [1738:111092] tick --- !!!!!!!!!!!!
2014-10-22 17:26:39.217 [1738:111092] tick --- !!!!!!!!!!!!
2014-10-22 17:26:39.764 [1738:111092] tick --- !!!!!!!!!!!!
2014-10-22 17:26:39.764 [1738:111092] I no longer exist --- WTF!

重申一下,正如 AnujYadav 指出的那样,如果您在父 VC 中使用属性来表示“红色”...

@property (strong) Red *red;

然后

self.red = (Red *)[self.storyboard
 instantiateViewControllerWithIdentifier:@"RedID"];

等...确实这不起作用。在这种情况下,您必须在父级中设置 self.red=nil,否则它不会消失。

【讨论】:

  • 感谢您在这里分享您的研究!一段时间以来,我的自定义容器视图控制器中有一个烦人(很少发生)的错误,这可能会帮助我找到它。
  • 是的,关于这个问题有很多困惑。希望有帮助!
【解决方案2】:

这是一个比视图控制器包含更多的内存管理问题。不,你不需要把 nil 放在那里,但是......

您假设您对它有引用。问题是:它是强引用吗?如果是,那么您必须将其设为 nil,因为该视图控制器不会被释放。最简单的测试方法是将 -dealoc 方法添加到带有日志消息的 rm。

【讨论】:

  • 确实 - 这是一个记忆问题,所以,享受赏金吧! :)
【解决方案3】:

您的问题和答案似乎有所不同。在您的覆盖方法(回答)中,您没有将 ViewController 分配给任何强属性,并且有问题您具有强属性。我没有测试过代码,但我觉得你应该更新你的测试以拥有一个强大的属性。

我认为理想情况下我们应该“取消”该属性。否则,将从堆栈中删除视图控制器。

【讨论】:

  • 嗨 anuj -- 正确:在我输入的答案中的“此方法有效”示例中,正如它所说... “请注意,没有持有 rr 的属性 - 它只是在该类别中即时创建和添加。”
  • 嗨,乔 -- 抱歉,我错过了。您是否也检查过强属性?
  • 嘿 Anuj -- 完全正确。正如您所期望的,如果您在父 VC 中使用属性……它不会消失! (FTR 请注意,我实际上只是使用一个类别来完成这项工作.. 从 VC 中它只是调用 [self showOverlay];,它甚至没有提到“Red”类。)
猜你喜欢
  • 2014-04-13
  • 2021-08-11
  • 1970-01-01
  • 2014-09-07
  • 2011-04-21
  • 2012-07-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多