如何在NSMutableArray viewControllers中释放viewController及其视图?

时间:2011-03-29 22:10:28

标签: objective-c iphone ipad memory memory-management

我的内存管理存在很大问题。实际上有一个大杂志,每个页面都用自己的PageViewController进行渲染。我的代码完全基于Apple文档的PageControl样本,如果你们有时见过的话。

因此,在我的“MainViewController”的viewDidLoad中,我创建了一个充满NSNull对象的NSMutableArray = self.viewControllers。我将我的[self loadScrollViewPage:page];称为我的第一页和第二页。当用户导航到更多页面时,我调用(来自scrollViewDidScroll)更多加载[self loadScrollViewPage:nextPage];,因为应用程序将需要它。我也实现了一个unloadScrollViewPage:page因为杂志太大了,如果我不这样做,记忆就会消失。

所以,这是我的代码:

- (void)loadScrollViewPage:(int)pageNumber
{
    if ((pageNumber < 0) || (pageNumber >= [self.viewControllers count]))
        return;

    PageViewController *controller = [self.viewControllers objectAtIndex:pageNumber];
    if ((NSNull *)controller == [NSNull null])
    {
        controller = [[PageViewController alloc] initWithPage:[self.pages objectAtIndex:pageNumber]];
        [self.viewControllers replaceObjectAtIndex:pageNumber withObject:controller];
        [controller release];
    }

    if (controller.view.superview == nil)
    {
        CGRect frame = mainpageScrollView.frame;
        frame.origin.x = 0;
        frame.origin.y = frame.size.height * pageNumber;
        controller.view.frame = frame;
        [mainpageScrollView addSubview:controller.view];
    }
}
- (void)unloadScrollViewPage:(int)pageNumber
{
    if ((pageNumber < 0) || (pageNumber >= [self.viewControllers count]))
        return;

    if ((NSNull *)[self.viewControllers objectAtIndex:pageNumber] != [NSNull null])
    {
        [[[self.viewControllers objectAtIndex:pageNumber] view] removeFromSuperview];
        [self.viewControllers removeObjectAtIndex:pageNumber];
        [self.viewControllers replaceObjectAtIndex:pageNumber withObject:[NSNull null]];
    }
}

问题是,无论我调用unloadScrollViewPage多少次,当我调用loadScrollViewPage并且永远不会减少unloadScrollViewPage时,内存仍会增加大小。那么,当用户进入10页(300页,大声笑?)时,我的应用程序的内存大小为100Mb,当然,它会崩溃:(

我的问题是:

  • 我是否正确地从我的self.viewControllers NSMutableArray?
  • 释放内存
  • 当我从self.viewControllers中删除ObjectAtIndex:pageNumber时,我在他们看到的每个控制器的视图(MainViewController的视图)将释放它?如果没有,我该怎么办?这是我的问题吗?

先谢谢。

修改

看起来 Firoze Lafeer 在开始时是正确的,问题是我的UIImage内存管理和我的观点保留。我只是设法删除每个UIView的SuperSuperview。对于图像,看起来像使用[UIImage imageNamed]它实现了一个缓存(当ios想要¬¬时释放它)。我只是改变使用[UIImage imageWithData:imageData];的方式,它没有实现缓存,现在我的所有对象都很开心。谢谢大家。 :)

2 个答案:

答案 0 :(得分:0)

是的,当您将每个视图添加到滚动视图时,滚动视图将保留该视图。因此,在卸载每个页面时,您必须删除每个视图。

顺便说一句,我想你会发现视图控制器本身根本不占用很多内存。意见是更大的问题。

答案 1 :(得分:0)

其余的代码看起来应该按照您的预期方式运行,但这两行可能不正确。

    [self.viewControllers removeObjectAtIndex:pageNumber];
    [self.viewControllers replaceObjectAtIndex:pageNumber withObject:[NSNull null]];

第一行是删除对象并将其上方的所有索引减1,因此您的数组将更小一个。然后,您在对象上调用replaceObject,该对象曾经比您删除的对象高一个索引。这两行代码将在每次调用时将数组的大小减小一,直到你通过数组的实际长度时得到一个越界异常。你可以删除removeObject行,replaceObject将释放该对象它是自己的,同时让你的阵列大小相同。

这可能无法解决您的问题,因为它会以相同的方式减少保留计数器。也许发布调用这些方法的代码会有所帮助。