cocoa - CALayer ScrollView 因许多项目而变慢

标签 cocoa macos nsscrollview

嘿,我在 NSScrollView 内的层支持的 NSView 中遇到了 CALayers 的性能问题。我有一个 ScrollView ,其中填充了一堆 CALayer 实例,一个堆叠在下一个实例之上。现在我所做的就是在它们周围设置边框,这样我就可以看到它们。该层中没有其他任何内容。

性能看起来不错,直到我的 ScrollView 达到 1500 左右。当我输入 1500 时,当我向下滚动列表时,性能非常好,直到到达第 1000 项左右。然后应用程序突然开始挂起。这并不是一个逐渐放缓的过程,而这正是我所期望的,如果它刚刚达到其容量的话。就像应用程序撞到了砖墙一样。

当我在图层的绘制方法中调用 CGContextFillRect 时,速度减慢发生在第 300 项左右。我假设这可能与显卡内存填满或其他原因有关?当 CALayers 在 ScrollView 中位于屏幕外时,我是否需要执行某些操作来释放 CALayers 的资源?

我注意到,如果我不在图层上设置NeedsDisplay,我可以在不减速的情况下到达 1500 个项目的末尾。但这不是一个解决方案,因为我有一些必须在图层中执行的自定义绘图。我不确定这是否可以解决问题,或者只是使其在图层中显示更多数量的项目。理想情况下,我希望它能够完全扩展, ScrollView 中包含数千个项目(当然在合理范围内)。实际上,我应该期望能够以这种方式显示多少个空项目?

#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

最佳答案

我发现这是因为我用自定义绘图填充每个图层,它们似乎都被缓存为单独的图像,即使它们共享很多公共(public)数据,所以我转而只创建十几个 CALayers,填充它们的“contents”属性,并将它们作为子图层添加到主图层中。这似乎让事情变得更加快捷。

关于cocoa - CALayer ScrollView 因许多项目而变慢,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5712095/

相关文章:

cocoa - 我如何用 Cocoa 创建一个透明且非矩形的 NSWindow?

cocoa - 如果不需要使其失效,是否有任何理由保留预定的 NSTimer?

objective-c - .mm 文件上的 NSLog

cocoa - 限制 Cocoa 中的滚动弹性(NSScrollView)

Swift OSX 动态添加项目到滚动列表

cocoa - 设置 nsview 大小

cocoa - 如何以不同的颜色显示旋转的 NSProgressIndicator?

objective-c - 通过 API 使用 iTunes 的 Up Next 功能

xcode - 无法将字符串类型的值转换为预期的参数类型 soundex

objective-c - 使用 Xcode 的文本替换服务 - 不替换选定的文本