【问题标题】:UINavigationController and memory managementUINavigationController 和内存管理
【发布时间】:2011-02-18 15:55:31
【问题描述】:
- (void)launchSearch 
{
 EventsSearchViewController *searchController = [[EventsSearchViewController alloc] initWithNibName:@"EventsSearchView" bundle:nil];
 [self.navigationController pushViewController:searchController animated:YES];
 //[searchController release]; 
}

注意[searchController release] 已被注释掉。我知道将searchController 推送到导航控制器会保留它,我应该从我的代码中释放它。毕竟我只是分配/初始化它,如果我不释放它,它会泄漏。

注释掉该行后,导航效果很好。如果它没有被注释掉,我可以导航到这个视图中,但是返回一个级别会崩溃并出现 *** -[CFArray release]: message sent to deallocated instance 0x443a9e0 错误。

这里发生了什么?当它消失时,NavigationController 是否会以某种方式为我释放它?

XCode 中 UINavigationController 模板上的样板已发布新推送的控制器。但是当我这样做时,它会失败。

---编辑----

所以今天早上,我坐下来,它起作用了。没有真正的线索为什么。叹息。

然后,将我认为我学到的知识应用到同一控制器的另一块上,我做了以下操作。昨天我有这段代码,没有发布声明,因为它不能正常工作。所以今天早上我添加了它们来创建:

- (IBAction)switchView:(id)sender
{
    UISegmentedControl *seg = (UISegmentedControl *)sender;
    NSInteger choice = [seg selectedSegmentIndex];

    NSArray *array = [mainView subviews];
    UIView *oldView = [array objectAtIndex:0];
    [oldView removeFromSuperview];

    if (choice == 0) {
        tableController = [[EventsTableViewController alloc]
            initWithNibName:@"EventsTableView" bundle:nil];
            [mainView addSubview:tableController.view];
            [tableController release];
    }

    if (choice == 1) {
        calendarController = [[EventsCalendarViewController alloc]
            initWithNibName:@"EventsCalendarView" bundle:nil];
        [mainView addSubview:calendarController.view];
        [calendarController release];
    }
    if (choice == 2) {
        mapController = [[EventsMapViewController alloc]
            initWithNibName:@"EventsMapView" bundle:nil];
        [mainView addSubview:mapController.view];
        [mapController release];
    }
}

这样设置后,当我进入视图时,我的视图的主入口充满了 EventsTableViewController 的视图,我可以单击 mapView 和 calendarView,但是当我返回 tableView 时,我死了,因为正在释放的实例上调用表委托方法。

所以我把所有这些控制器都合成了属性,所以我可以在[dealloc] 中发布它们。这似乎可行,但真正的问题是为什么将这些视图添加为子视图并不能保留它们,将所有权传递给它所属的新视图,允许我在那里释放它们?

【问题讨论】:

  • 如果注释掉 pushViewController 行但取消注释 release 行会怎样?发布会崩溃吗?
  • 不。 UI 中显然没有发生任何事情,但是 NSLog 告诉我它已经到了该方法的末尾。但这并不是说即使按下该版本也会崩溃。当我从刚刚按下的 searchController 备份时,那是我崩溃的时候。
  • 好的,这是最糟糕的事情。今天早上它起作用了。我留下了推动和释放,我不能让它崩溃。所以然后我开始寻找其他地方,我正在将控制器推到导航上,在那里我离开了那些释放,因为否则它不起作用,当我将它们添加回来时,发生了一些更奇怪的事情。我会用相关代码更新上面的问题。

标签: iphone memory-management uinavigationcontroller


【解决方案1】:

我猜错误在于 EventsSearchViewController 的初始化。它是否错误地返回了一个自动释放的自我?

【讨论】:

  • 只有当它的[super init] 是。我没有覆盖它的 init 方法。我还应该注意,这不是唯一发生这种情况的 ViewController。我在这个应用程序中还有其他地方,如果我在将控制器推送到导航控制器后显式释放控制器,我稍后会调用丢失的对象。
  • 我认为您没有在代码的其他地方使用 searchController ?一旦navigationController返回它就无效了。
  • 不,这是唯一的地方。
  • 好吧,您发布的 3 行代码没有任何问题(假设您将版本放回原处),因此问题出在您项目的其他地方。发布更多 - 我会看看。
  • 谢谢--我明天一进去就看看。我应该看的任何部分?可能是根视图控制器中设置navigationcontrol业务的地方?
【解决方案2】:

看起来EventsSearchViewController 正在分配一个数组,然后过度释放它,其中一个版本可能在其dealloc 中。

如果您注释掉 release,您的 EventsSearchViewController 永远不会被释放(它会泄漏)。因此,由于它自己的dealloc 导致的错误将被屏蔽,因为不会调用该方法。释放控制器是正确的,但是控制器本身还有另一个 bug,它只在 dealloc 时出现。

也可能是因为 dealloc 正在释放一个自动释放的数组,所以您的代码中可能没有两个显式的释放调用。但它看起来很像在导致问题的 dealloc 中释放一些东西。

【讨论】:

  • 我用阵列业务向你扔了一个假货。原来有问题的数组正在那个控制器中使用,而我只是在用它做一些愚蠢的事情。
【解决方案3】:

哇,伙计们。非常感谢您的所有回复——可悲的是,我给你们所有人带来了一场可怕的鹅追逐。

我的 NavigationView 导航事件对象(本地艺术事件)的 NSArray。我的表格视图深入到详细视图。

我的详细视图中有以下内容:

-(void)loadEvent:(Event *)event
{
    thisEvent = event;          
}

在将详细视图推送到导航堆栈之前,我会从我的表格视图中调用它。 thisEvent 是 Event 类型的合成属性,因此,由于它是合成的,因此我尽职尽责地 release'd 将其放入 [dealloc]

你们中的许多人已经看到了这个问题。备份到表格视图,当我滚动以显示我刚刚看到的那个时,它会构建自定义表格行,因此它会从事件中获取标题属性...。我刚刚在详细信息中发布控制器。轰隆隆。

我在上面的 loadEvent: 方法中添加了retain,然后崩溃,它们消失了。

这一切都与导航控制器保留和释放视图有关。这是关于意外过度释放我正在导航的数据对象。我发现这一点的部分原因是,我在每个视图控制器的[dealloc] 中进行了 NSLogged,我现在可以看到它们的行为完全符合它们应有的状态。

谢谢!我非常喜欢这个网站。

【讨论】:

    猜你喜欢
    • 2013-08-07
    • 1970-01-01
    • 1970-01-01
    • 2012-03-07
    • 2014-07-13
    • 2010-10-16
    • 2016-10-12
    • 1970-01-01
    • 2021-01-23
    相关资源
    最近更新 更多