解除分配后的CATextLayer内存残留

时间:2011-03-06 12:00:36

标签: iphone objective-c ios memory calayer

我刚刚进入iPhone开发阶段,我仍然在搞清楚这些问题。在测试各种CALayer和CATextLayer行为时,我偶然发现了一些有趣的事情。

我创建了一个iPhone测试应用程序,在视图中只有2个UIButton。其中一个分别调用'allocateAutoReleasedLayers'函数和另一个'deallocateAutoReleasedLayers'。以下代码片段代表函数体。

-(IBAction)allocateAutoReleasedLayers:(id)sender
{
    for ( int i = 0; i < 500; ++i )
    {
        CALayer * layer = [ CALayer layer ];
        [ master addSublayer: layer ];
    }
}

-(IBAction)deallocateAutoReleasedLayers:(id)sender
{
    master.sublayers = nil;
}

现在,测试的目的是了解iOS如何处理图层自动释放。当使用'Allocations'分析器运行时,应用程序占用646.452字节的内存。点击“分配”按钮后,内存使用量上升到719.228字节,以托管创建的所有500个空图层,这是正常的,因为当我按下“解除分配”按钮时,使用的内存回落到656.732字节(我猜在分配之前和解除分配之后使用的内存不匹配是iOS内部内存管理的结果。

当我改变“分配”程序的一部分来创建CATextLayers而不是CALayers时,会发生有趣的部分。

-(IBAction)allocateAutoReleasedLayers:(id)sender
{
    for ( int i = 0; i < 500; ++i )
    {
        NSString * layerString = [ [NSString alloc ] initWithFormat: @"1231" ];
        CATextLayer * textLayer = [ CATextLayer layer ];
        [ textLayer setString: layerString ];
        [ textLayer setFrame: CGRectMake( 0, 0, 100, 200) ];
        [ textLayer setFont: @"Helvetica-Bold" ];
        [ textLayer setFontSize: 20 ];
        [ master addSublayer: textLayer ];
        [ layerString release ];
    }
}

应用程序在分配之前以通常的651.868字节使用率开始,并且上升到使用的2.13MB(我猜CATextLayers在内存使用上相当沉重),并且在重新分配后,内存将回落到950.372字节。

现在,我的问题如下:在处理CATextLayers时,在分配之前和解除分配之后导致300kB差异的原因是什么。我想我对iOS管理内存的方式的误解可能是原因,但我使用了与创建CALayer时使用的CATextLayer完全相同的方式。

提前致谢和最诚挚的问候!

1 个答案:

答案 0 :(得分:2)

我在模拟器上运行你的代码,我看不到这种行为。以下是我执行的步骤:

1)在“Allocations”工具下运行app 2)等到它完全启动 3)标记堆 - &gt;堆(0)
4)a)用allocateAutoReleasedLayers:分配CATextLayer实例    b)与deallocateAutoReleasedLayers:解除分配    c)标记堆 - &gt;堆(1)

操作4为我们提供了一个测试模式(Allocate-Deallocate-Mark堆),所以

5)ADM(2) - &gt;堆(2)
6)ADM(3) - &gt;堆(3)
7)ADM(4) - &gt;堆(4)
...

执行ADM(n)时堆(n)和堆(n-1)之间的差异约为2K,执行ADM(n + 1)时降至0.5-1k(这可能是因为框架重新创建了一些东西)并发布旧的,我可以注意到CGDataProvider为例)。无论如何,Heap(n + 1)-Heap(n)中的内容包含与CSEvent,UITouchData等无关的内容,这些内容很可能被分配用于处理按钮点击。

您是在设备还是模拟器上进行测试?你重复这个ADM循环多少次?后续堆之间的差异内容是什么?这很有趣,因为300k对我来说似乎太过分了。