代码之家  ›  专栏  ›  技术社区  ›  Dan Ray

ui导航控制器和内存管理

  •  1
  • Dan Ray  · 技术社区  · 14 年前
    - (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 错误。

    这里发生了什么?导航控制器是不是在我看不见的时候为我释放了它?

    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];
        }
    }
    

    当它设置成这样时,当我进入视图时,视图的主门户中充满了EventStableView控制器的视图,我可以单击到MapView和CalendarView,但是当我返回到TableView时,我死了,因为表委托方法是在一个已释放的实例上调用的。

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

    3 回复  |  直到 14 年前
        1
  •  1
  •   Dan Ray    14 年前

    哇,伙计们。非常感谢你们所有的回应——可悲的是,我把你们所有人都送上了一个可怕的goosecyphase。

    我的导航视图导航一系列事件对象(本地艺术事件)。我的表视图向下钻取到详细视图。

    我的详细视图包含以下内容:

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

    在将细节视图推到导航堆栈之前,我从我的表视图调用它。这个事件是类型事件的合成属性,所以自从它被合成之后,我尽职尽责地 release 在里面 [dealloc] .

    你们中的许多人已经看到了这个问题。备份到表视图时,当我滚动到显示刚才看到的表时,它将构建自定义表行,因此它将从事件中获取标题属性….我刚在细节控制器里发布的。繁荣。

    我添加了一个 retain 到上面的loadEvent:方法和崩溃,它们都消失了。

    这些都不是关于导航控制器保留和发布的视图。这是因为不小心释放了我正在导航的数据对象。我发现的部分原因是,我登录了 [DELOLC] 在这些视图控制器中,我现在可以看到它们的行为正是它们应该的。

    谢谢!我很喜欢这个网站。

        2
  •  0
  •   Andiih    14 年前

    我猜是因为EventsSearchViewController的初始化。它是不是错误地返回了一个自动释放的自我?

        3
  •  0
  •   Tom Harrington    14 年前

    看起来像 EventsSearchViewController 正在分配一个数组,然后过度释放它,其中一个释放可能位于 dealloc .

    如果你对 release 你的 事件搜索视图控制器 永远不会释放(泄漏)。因此,由于自身原因而发生的错误 释放内存 将被屏蔽,因为不会调用该方法。释放控制器是正确的,但是控制器本身还有另一个bug,它只在dealloc时出现。

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