ねえ、NSScrollView内のレイヤーに裏打ちされたNSViewのCALayersでパフォーマンスの問題が発生しています。たくさんのCALayerインスタンスを積み上げて、次のインスタンスの上に積み重ねたスクロールビューがあります。今私がしているのは、それらを見ることができるようにそれらの周りに境界線を置くことだけです。レイヤーには他に何もありません。
スクロールビューで約1500になるまで、パフォーマンスは問題ないようです。1500を入れると、リストを下にスクロールしてアイテム1000付近に到達するまで、パフォーマンスが向上します。その後、突然アプリがハングし始めます。それは、それがちょうどその容量に達した場合に私が期待するものである段階的な減速ではありません。アプリがレンガの壁にぶつかるようなものです。
レイヤーの描画メソッドでCGContextFillRectを呼び出すと、アイテム300付近で速度低下が発生します。これは、ビデオカードのメモリがいっぱいになるか何かに関係していると思いますか?スクロールビューでCALayersが画面外にあるときに、CALayersのリソースを解放するために何かをする必要がありますか?
レイヤーにNeedsDisplayを設定しないと、速度を落とさずに1500アイテムの最後に到達できることに気づきました。ただし、レイヤーで実行する必要のあるカスタム描画があるため、これは解決策ではありません。それで問題が解決するのか、それともレイヤー内のアイテムの数が増えるだけなのかはわかりません。理想的には、これをスクロールビューの何千ものアイテムで完全にスケーラブルにしたいと思います(もちろん理由の範囲内で)。現実的には、これらの空のアイテムのうち、この方法で表示できると期待できるものはいくつありますか?
#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