【问题标题】:Memory management when adding a UIImageView to another viewController's view from another viewController's view将 UIImageView 从另一个 viewController 的视图添加到另一个 viewController 的视图时的内存管理
【发布时间】:2011-03-07 21:14:33
【问题描述】:

所以看起来我在整个项目中都没有检测到泄漏,而且我有很多部分可以做各种各样的事情。

但是,我发现我遇到了一些分配问题,通过泄漏仪器中的标记堆向我证明了这一点,这在使用带有外部屏幕的 iPad 时经常发生。该应用程序被编程为在连接到外部屏幕时表现不同。

我有一个可以进出的可缩放 UIScrollView 地图部分。单独使用 iPad 并检查标记堆时,堆增长最终会下降到 0 字节,这很好。但是,插入外部屏幕后,将图像发送到外部屏幕,该外部屏幕使用另一个视图控制器,并且在退出地图时检查标记堆大约每次都在 6-7 MB 左右,而其他堆没有太大减少增长。不好。

我发现,我完全没有正确处理外部 UIImageView 的发布,当我浏览它时,这对我来说很明显。我稍后会解释更多。

在我继续解释之前,重要的事情,我很抱歉花了这么长时间,但我发誓我听说有一个例外,如果它从另一个视图添加到另一个视图,则不将分配的对象放入 dealloc,因为我不拥有它,因此不负责解除分配。无论我是否解除分配,我都会得到相同的行为。但我实际上不认为它会像我的代码当前设置的方式那样解除分配。所以我认为我的问题是我没有从内存中释放图像视图......但问题仍然存在,在这种情况下我应该在哪里做!

在视图 A 的 initWithFrame 方法中,如果已连接,我会将视图添加到外部屏幕:

    if(exScreenEnabled==1){
        mapImageViewEx = [[UIImageView alloc] init];

        CGPoint p = mapScrollView.contentOffset;
        mapImageViewEx.frame = CGRectMake((p.x*-1), (p.y*-1), mapImageView.frame.size.width, mapImageView.frame.size.height);

        NSString *mapExFileLocation = [[NSBundle mainBundle] pathForResource:[map_List objectAtIndex:mapNum] ofType:@"png"];
        NSData *mapExIMGData = [NSData dataWithContentsOfFile:mapExFileLocation];
        mapImageViewEx.image = [UIImage imageWithData:mapExIMGData];

        UIView *containerExViewP = (UIView*)[del.switchExVC.view viewWithTag:9000];

        [containerExViewP addSubview:mapImageViewEx];

    }

在外部 viewController 的 viewDidLoad 方法中,当应用程序启动并且用户选择屏幕分辨率时,已经添加了一个 containerView。工作原理与 iPad 窗口的视图控制器几乎相同,用于换入和换出视图:

CGRect frame = CGRectMake(0, 0, 1024, 768);
containerExView = [[UIView alloc] initWithFrame:frame];
[containerExView setTag:9000];

self.view = containerExView;

我们就叫这个外部 viewController 的“View B”

所以这看起来像问题开始的地方:当用户在地图中按下后退按钮时,如果连接了外部屏幕,则视图 A 执行视图 B 侦听的 NSNotificationCenter,以删除视图 B 中的子视图容器。这是视图 B 中的方法:

- (void)removeExView{
    [[self.view.subviews objectAtIndex:0] removeFromSuperview];
    NSLog(@"REMOVED EX VIEW");


    UIImage *idleExImage = [UIImage imageNamed:@"idle4.png"];
    UIImageView *idleExImageView = [[UIImageView alloc] initWithImage:(UIImage *)idleExImage];
    CGRect idleExFrame = CGRectMake(0, 0, 1024, 768);
    idleExImageView.frame = idleExFrame;
    [self.view addSubview:idleExImageView];

    [idleExImageView release];
}

子视图从索引 0 处的视图 B 的容器中删除,然后显示默认图像。

所以,我最好的猜测是,即使子视图(即图像视图)被删除,它也不一定会从内存中释放。但是您将如何访问它?这甚至是问题吗?也许它确实必须被释放,但永远无法达到这一点,因为视图首先被意外删除。我只是不知道,因为我还不熟悉这种情况应该如何正确处理。提前感谢您提供的任何帮助。

【问题讨论】:

    标签: iphone ipad uiview uiimageview screen


    【解决方案1】:

    这有点难猜,但我会说是这些台词

        mapImageViewEx = [[UIImageView alloc] init];
        // snipped some code for clarity
        [containerExViewP addSubview:mapImageViewEx];
    
        containerExView = [[UIView alloc] initWithFrame:frame];
        // snipped some code for clarity
        self.view = containerExView;
    

    这些可以而且应该在它们被添加到视图层次结构后释放

        [mapImageViewEx release];
        [containerExView release];
    

    除非您有意为上述 sn-ps 中未显示的内容保留对这些内容的引用。

    【讨论】:

    • 在视图 A 我有 [mapImageViewEx 版本];在 dealloc 中,因为它是在实现中作为静态权利制作的:静态 UIImageView *mapImageViewEx;。它在整个文件中以不同的方法引用。 containerExView 在视图控制器 View B 的 dealloc 中释放。
    【解决方案2】:

    [containerExViewP addSubview:mapImageViewEx];

    在这一行之后使用[containerExViewP release];

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-07-11
      • 1970-01-01
      • 2015-03-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多