开发者

CALayer scroll view slowdown with many items

Hey, I'm having a performance problem with CALayers in a layer backed NSView inside an NSScrollView. I've got a scroll view that I populate with a bunch of CALayer instances, stacked one on top of the next. Right now all I am doing is putting a border around them so I can see them. There is nothing else in the layer.

Performance seems fine until I have around 1500 or so in the scroll view. When I put 1500 in, the performance is great as I scroll down the list, until I get to around item 1000. Then very suddenly the app starts to hang. It's not a gradual slowdown which is what I would expect if it was just reaching it's capacity. It's like the app hits a brick wall.

When I call CGContextFillRect in the draw method of the layers, the slowdown happens around item 300. I'm assuming this has something to do with maybe the video card memory filling up or something? Do I need to do something to free the resources of the CALayers when they are offscreen in my scroll view?

I've noticed that if I don't setNeedsDisplay on my layers, I can get to the end of 1500 items without slowdowns. This is not a solution however, as I have some custom drawing that I must perform in the layer. I'm not sure if that solves the problem, or just makes it show up with a greater number of items in the layer. Ideally I would like this to be fully scalable with thousands of items in the scroll view (within reason of course). Realistically, how many of these empty items should I expect t开发者_高级运维o be able to display in this way?

#import "ShelfView.h"
#import <Quartz/Quartz.h>

@implementation ShelfView

- (void) awakeFromNib
{
    CALayer *rootLayer = [CALayer layer];
    rootLayer.layoutManager = self;
    rootLayer.geometryFlipped = YES;

    [self setLayer:rootLayer];
    [self setWantsLayer:YES];

    int numItemsOnShelf = 1500;

    for(NSUInteger i = 0; i < numItemsOnShelf; i++) {
        CALayer* shelfItem = [CALayer layer];
        [shelfItem setBorderColor:CGColorCreateGenericRGB(1.0, 0.0, 0.0, 1.0)];
        [shelfItem setBorderWidth:1];
        [shelfItem setNeedsDisplay];
        [rootLayer addSublayer:shelfItem];
    }

    [rootLayer setNeedsLayout];
}

- (void)layoutSublayersOfLayer:(CALayer *)layer
{
    float y = 10;

    int totalItems = (int)[[layer sublayers] count];

    for(int i = 0; i < totalItems; i++)
    {
        CALayer* item = [[layer sublayers] objectAtIndex:i];

        CGRect frame = [item frame];            
        frame.origin.x = self.frame.size.width / 2 - 200;
        frame.origin.y = y;
        frame.size.width = 400;
        frame.size.height = 400;

        [CATransaction begin];
        [CATransaction setAnimationDuration:0.0];

        [item setFrame:CGRectIntegral(frame)];

        [CATransaction commit];
        y += 410;
    }

    NSRect thisFrame = [self frame];
    thisFrame.size.height = y;

    if(thisFrame.size.height < self.superview.frame.size.height) 
        thisFrame.size.height = self.superview.frame.size.height;

    [self setFrame:thisFrame];
}

- (BOOL) isFlipped
{
    return YES;
}

@end


I found out it was because I was filling each layer with custom drawing, they seemed to all be cached as separate images, even though they shared a lot of common data, so I switched to just creating a dozen CALayers, filling their "contents" property, and adding them as sublayers to a main layer. This seemed to make things MUCH zippier.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜