0

我有一个具有多个 UIView 子类的应用程序,它们充当 UIScrollView 的页面。UIView 来回移动以向用户提供无缝体验。由于视图的内容绘制起来相当慢,它呈现在一个共享的 CGBitmapContext 上,由 NSOperation 子类的锁保护 - 在 NSOperationQueue 中一次执行 - 包装在 UIImage 中,然后由主线程用于更新内容的意见。

-(void)main {

NSAutoreleasePool * pool = [[NSAutoreleasePool alloc]init];

if([self isCancelled]) {
    return;
}
if(nil == data) {
    return; 
}

// Buffer is the shared instance of a CG Bitmap Context wrapper class
// data is a dictionary
CGImageRef img = [buffer imageCreateWithData:data];
UIImage * image = [[UIImage alloc]initWithCGImage:img];
CGImageRelease(img);

if([self isCancelled]) {
    [image release];
    return;
}

NSDictionary * result = [[NSDictionary alloc]initWithObjectsAndKeys:image,@"image",id,@"id",nil];

// target is the instance of the UIView subclass that will use
// the image
[target performSelectorOnMainThread:@selector(updateContentWithData:) withObject:result waitUntilDone:NO];

[result release];
[image release];

[pool release];
}

UIView 子类的 updateContentWithData: 在主线程上执行也一样简单

-(void)updateContentWithData:(NSDictionary *)someData {

NSDictionary * data = [someData retain];

if([[data valueForKey:@"id"]isEqualToString:[self pendingRequestId]]) {

    UIImage * image = [data valueForKey:@"image"];
    [self setCurrentImage:image];
    [self setNeedsDisplay];

}

// If the image has not been retained, it should be released together
// with the dictionary retaining it
[data release];
}

子类的 drawLayer:inContext: 方法只会从 UIImage 中获取 CGImage 并使用它来更新支持层或它的一部分。该过程不涉及保留或释放。

问题是一段时间后我的内存不足。UIView 的数量是静态的。CGImageRef 和 UIImage 被正确地创建、保留和释放(或者在我看来是这样)。Instruments 没有显示任何泄漏,只是可用内存不断下降,上升几次,然后下降甚至更低,直到应用程序终止。在此之前,该应用程序会循环浏览大约 2-300 个上述页面,但我希望在已经快速浏览了一堆页面之后,内存使用率会达到或多或少稳定的已用内存水平,或者,因为图像大小高达 3MB,较早耗尽。

任何建议将不胜感激。

4

1 回答 1

0

我意识到这是一个旧帖子,但如果它对其他人有帮助....这看起来像是内存碎片的情况。我们有一个行为相同的应用程序。应用程序实际分配的内存量从未达到危险水平,但如果您查看应用程序的常驻内存量(使用分配工具或活动监视器工具中的 VM Tracker 快照),它会随着时间的推移无情地攀升,直到一个不是很大的瞬时峰值会杀死应用程序。

有问题的应用程序是一个多线程应用程序,它会进行大量大小范围内的瞬态分配,其时间无法预测或控制。这样的应用程序必须对释放不需要的内存分配感到偏执,不是因为它们本身占用了太多内存,而是因为它们可以创建阻止更大图像适合分配的块的孔。即使是容易被忽略的较小分配在碎片中也很重要(假设低级分配器按大小对分配进行分组,这在一定程度上是有帮助的)。内存区域在理论上有助于解决碎片问题,但很难发挥作用,至少在我的经验中是这样。此外,使用自定义自动释放池,或者更好的是,尽可能多地使用 alloc/init,并尽早释放。

于 2011-02-03T21:42:01.900 回答