0

这与另一篇文章有​​些相关——但那篇文章有点搞砸了——所以我从头开始:

我有一个 CATiledLayer,里面有一个巨大的图像(5780x6700px)。

平铺层位于滚动视图中。当我开始滚动时,一切都很好,直到明显渲染了太多图块。然后我收到内存警告,应用程序崩溃。

当我收到内存警告时,我试图从视图中删除 tiledlayer,清除它的内容(rootLayer.contents = nil AND tiledLayer.contents = nil),然后将其重新附加到视图中。没用...

将感谢任何输入...

编辑:

感谢到目前为止的提示。我的一些假设似乎是错误的。我将图像加载到一个函数中,然后保留它——我猜这与 CATiledLayer 的行为相矛盾。加上UIImage imageNamed:似乎也导致了一些错误。现在我加载图像drawLayer:(CALayer *) inContentext(CGContextRef) ctx并使用UIImage imageWithContentsOfFile:它来加载它。

这似乎工作而不会导致内存变低。

但是 - 瓷砖的绘制速度非常缓慢:(

这是我对 tiledLayer 的设置:

-(CATiledLayer *)initTiledLayers: (int)level{

    //[tiledLayer release];

    CGRect pageRect;

    CATiledLayer *myLayer = [CATiledLayer layer];
    myLayer.delegate = self;

    if(level == 1){     
        pageRect = CGRectMake(0,  0,  690, 800);
        myLayer.tileSize = CGSizeMake(800, 800);
        myLayer.levelsOfDetail = 10;
        myLayer.levelsOfDetailBias = 2;
    }else if(level == 2){
        pageRect = CGRectMake(0,  0,  1445, 1675);
        myLayer.tileSize = CGSizeMake(600, 600);
        myLayer.levelsOfDetail = 8;
        myLayer.levelsOfDetailBias = 2;
    }else if(level == 3){   
        pageRect = CGRectMake(0,  0,  2890, 3350);
        myLayer.tileSize = CGSizeMake(400, 400);
        myLayer.levelsOfDetail = 4;
        myLayer.levelsOfDetailBias = 1;
    }else if(level == 4){
        pageRect = CGRectMake(0,  0, 5780, 6700);
        myLayer.tileSize = CGSizeMake(150, 150);
        myLayer.levelsOfDetail = 4;
        myLayer.levelsOfDetailBias = 0;
    }

    myLayer.frame = pageRect;

    return myLayer;
    [myLayer release];
}

(int)level 指示要使用的图像(我在某些缩放级别上切换图像)。Level4是最大的图像...

这是drawLayer函数:

- (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx
{
    CGContextSetRGBFillColor(ctx, 1.0, 1.0, 1.0, 1.0);
CGContextFillRect(ctx, CGContextGetClipBoundingBox(ctx));
CGContextTranslateCTM(ctx, 0.0, layer.bounds.size.height);
CGContextClearRect(ctx, CGRectMake(0,0,layer.bounds.size.width, layer.bounds.size.height));
CGContextScaleCTM(ctx, 1.0, -1.0);

    UIImage *map = [UIImage imageWithContentsOfFile: [[NSBundle mainBundle] pathForResource:[NSString stringWithFormat:@"Karte0%d", actLevel] ofType:@"jpg"]];
    UIImage *wanderwege = [UIImage imageWithContentsOfFile: [[NSBundle mainBundle] pathForResource:[NSString stringWithFormat:@"Karte0%d_wanderwege", actLevel] ofType:@"png"]];
    UIImage *rhb = [UIImage imageWithContentsOfFile: [[NSBundle mainBundle] pathForResource:[NSString stringWithFormat:@"Karte0%d_rhb", actLevel] ofType:@"png"]];
    UIImage *abstecher = [UIImage imageWithContentsOfFile: [[NSBundle mainBundle] pathForResource:[NSString stringWithFormat:@"Karte0%d_abstecher", actLevel] ofType:@"png"]];

    CGRect imageRect = CGRectMake (0.0, 0.0, map.size.width, map.size.height);
    CGContextDrawImage (ctx, imageRect, [map CGImage]);

    imageRect = CGRectMake (0.0, 0.0, wanderwege.size.width, wanderwege.size.height);
    CGContextDrawImage (ctx, imageRect, [wanderwege CGImage]);

    imageRect = CGRectMake (0.0, 0.0, rhb.size.width, rhb.size.height);
    CGContextDrawImage (ctx, imageRect, [rhb CGImage]);

    imageRect = CGRectMake (0.0, 0.0, abstecher.size.width, abstecher.size.height);
    CGContextDrawImage (ctx, imageRect, [abstecher CGImage]);

}

是的 - 我知道 - 我实际上在上下文中绘制了 4 个图像。PNG是我需要动态添加到主图像的叠加层......

我试图将图像合并为一个 - 但这似乎更加消耗内存/cpu ;)

非常感谢任何进一步的帮助!

4

3 回答 3

2

为什么要在委托回调中绘制所有图像?

问题是 CATiledLayer 将所有内容分成矩形并将剪辑的上下文传递给委托回调: - (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx

所有矩形都会发生这种情况,因为它们很多,并且您绘制的图像很大且耗时,因此整个过程会持续“很长时间”。

在我的实践中,我有许多小对象,只有当它们在剪辑上下文定义的框架内可见时才会被渲染。

在您的情况下(1 个大 pdf),我会尝试仅绘制图像的一部分。不确定它是否有帮助:)

于 2010-08-27T12:55:31.020 回答
1

您需要拆分大图像,因为 iOS 必须在内存中保持图像未压缩。如果将图像大小乘以每个像素 4 个字节,则消耗大量内存。

您需要以某种方式将它们预先分成两半和四分之一并将它们缓存到磁盘,然后从那里显示图块。请参阅 WWDC 2010 滚动视图演讲,该演讲展示了如何顺利完成此操作。

于 2011-06-20T10:28:51.697 回答
0

我发现,我没有正确使用 tiledLayer。此外,我使用 PNG 作为覆盖,并且必须正确设置 tiledLayer 上的混合模式以摆脱黑屏......

[编辑]并且不要忘记(正如安德鲁在下面提到的那样),必须将大图像切割成图块(例如,对于 PSD 进行缩放)。如果您将平铺层与一张大图像一起使用,则不起作用...

于 2010-08-21T01:31:44.280 回答