【问题标题】:why does my UIViewController get retained an extra time when using initWithNibName?为什么我的 UIViewController 在使用 initWithNibName 时会保留额外的时间?
【发布时间】:2011-10-03 16:41:07
【问题描述】:

我正在开发一个应用程序,该应用程序的主视图希望在触摸按钮时生成子视图。因此,当我收到按钮事件时,MainViewController 通过调用 initWithNibName 并将 ChildViewController 存储在 ivar 中来生成子视图。然后我通过附加动画并设置 childVC.view.hidden = NO 来显示 ChildView。

这可行,但我注意到 ChildViewController 在关闭 ChildView 后从未被释放。当我第一次访问子视图时,我意识到 ChildVC 的保留计数从 1 变为 2。因此,nib 加载内容中的某些内容似乎再次保留了我的 ChildVC(除了我在对象初始化期间期望的初始保留)。

谁能帮我弄清楚为什么 ChildVC 被保留了额外的时间,当我想关闭子视图时如何确保它被完全释放?

编辑:这里有一些代码,只是稍微简化了一点。这些是父视图控制器上的方法。

-(IBAction)onLaunchChildButtonTouched:(id)sender
{
    m_childViewController = [[ChildViewController alloc] initWithNibName:@"ChildViewController" bundle:nil];
    [m_childViewController setParentDelegate:self];  // this is a weak reference

    // m_childViewController retain count here is 1, as expected
    m_childViewController.view.hidden = YES;
    // m_childViewController retain count is now 2, not expected

    [self.view addSubview:m_childViewController.view];

    [self addTransitionEntrDir:YES];  // code omitted

    m_childViewController.view.hidden = NO;

}


-(void)onChildWantsToClose:(id)child
{
    NSAssert( child == m_childViewController, @"unexpected childVC" );

    // if child view is now hidden, we should remove it.
    if( m_childViewController != nil && m_childViewController.view.hidden )
    {
        [m_childViewController.view removeFromSuperview];
        [m_childViewController release]; m_childViewController = nil;

        // BUG: m_childViewController retain count is still 1 here, so it never gets released

    }
}

【问题讨论】:

  • 可能会显示您的实际代码?
  • 显示一些代码将有助于将 A 带入这个 Q。
  • 用一些代码更新了原始帖子。

标签: iphone objective-c memory-leaks


【解决方案1】:

没有代码很难准确地说出来,但是您确定您没有将您的ChildVC 分配给其他对象的retain 属性吗?这可以解释你看到的意想不到的retain。

很抱歉之前的回答,我试图传达同样的信息,但我把一切都搞混了。

旧答案: 请记住,UIViewController 的 view 属性被保留: 查看

控制器管理的视图。

@property(nonatomic, retain) UIView *view 所以,如果你这样分配它: childVC.view = [[xxxxx alloc] initWithNibName:...]; 这解释了你所看到的。 改用: childVC.view = [[[xxxxx alloc] initWithNibName:...] autorelease];

【讨论】:

  • 感谢您的回复。我正在使用 initWithNibName 来初始化 ViewController,而不是视图。然后(根据文档) View 属性将在我第一次访问它时自动从笔尖加载。我不是自动释放 ViewController,而是在子视图关闭时手动释放它。问题似乎是 ChildVC 被保留了额外的时间,我不知道为什么。
【解决方案2】:

我发现了问题,泄漏的 ChildViewController 正在实例化一个保留 ref 的对象。

有趣的是,我并没有简单地忘记发布这个引用。我确实接到了发布它的电话,但该代码从未运行,因为它假设 viewDidUnload 会运行并给我一个释放所有内容的机会,但它没有。我把 deinit 代码放在了 dealloc 中,现在它可以工作了。

【讨论】:

  • 当你在viewDidLoad 中addObserverForName:object:queue:usingBlock: 到NSNotificationCenter 时,会发生这种情况,并引用self,但只在dealloc 中删除Observer。 Dealloc 将永远不会被定义调用,因为该块将保留self。您可以对self 进行弱引用以帮助解决此问题,或者订阅/取消订阅viewWillAppear 和viewDidDisappear 中的通知等。
猜你喜欢
  • 2010-11-07
  • 1970-01-01
  • 2019-08-25
  • 1970-01-01
  • 2013-07-19
  • 2017-08-25
  • 2015-03-02
  • 2021-03-16
  • 2021-07-17
相关资源
最近更新 更多