内部に一連の画像が並んでロードされた UIScrollView があります。ここで私のアプリの例を見ることができます: http://www.42restaurants.com . 私の問題はメモリ使用量にあります。画面に表示されようとしている画像を遅延ロードし、画面に表示されていない画像をアンロードしたい。コードでわかるように、ロードする必要があるイメージを最小限に抑え、ロード部分を NSOperation に割り当てて、NSOperationQueue に配置します。ぎくしゃくしたスクロール体験を除けば、すべてがうまく機能します。
これをさらに最適化して、各画像の読み込み時間を最小限に抑えたり、スクロールがぎくしゃくしたりしないようにする方法について、誰かがアイデアを持っているかどうかはわかりません。
- (void)scrollViewDidScroll:(UIScrollView *)scrollView{
[self manageThumbs];
}
- (void) manageThumbs{
int centerIndex = [self centerThumbIndex];
if(lastCenterIndex == centerIndex){
return;
}
if(centerIndex >= totalThumbs){
return;
}
NSRange unloadRange;
NSRange loadRange;
int totalChange = lastCenterIndex - centerIndex;
if(totalChange > 0){ //scrolling backwards
loadRange.length = fabsf(totalChange);
loadRange.location = centerIndex - 5;
unloadRange.length = fabsf(totalChange);
unloadRange.location = centerIndex + 6;
}else if(totalChange < 0){ //scrolling forwards
unloadRange.length = fabsf(totalChange);
unloadRange.location = centerIndex - 6;
loadRange.length = fabsf(totalChange);
loadRange.location = centerIndex + 5;
}
[self unloadImages:unloadRange];
[self loadImages:loadRange];
lastCenterIndex = centerIndex;
return;
}
- (void) unloadImages:(NSRange)range{
UIScrollView *scrollView = (UIScrollView *)[[self.view subviews] objectAtIndex:0];
for(int i = 0; i < range.length && range.location + i < [scrollView.subviews count]; i++){
UIView *subview = [scrollView.subviews objectAtIndex:(range.location + i)];
if(subview != nil && [subview isKindOfClass:[ThumbnailView class]]){
ThumbnailView *thumbView = (ThumbnailView *)subview;
if(thumbView.loaded){
UnloadImageOperation *unloadOperation = [[UnloadImageOperation alloc] initWithOperableImage:thumbView];
[queue addOperation:unloadOperation];
[unloadOperation release];
}
}
}
}
- (void) loadImages:(NSRange)range{
UIScrollView *scrollView = (UIScrollView *)[[self.view subviews] objectAtIndex:0];
for(int i = 0; i < range.length && range.location + i < [scrollView.subviews count]; i++){
UIView *subview = [scrollView.subviews objectAtIndex:(range.location + i)];
if(subview != nil && [subview isKindOfClass:[ThumbnailView class]]){
ThumbnailView *thumbView = (ThumbnailView *)subview;
if(!thumbView.loaded){
LoadImageOperation *loadOperation = [[LoadImageOperation alloc] initWithOperableImage:thumbView];
[queue addOperation:loadOperation];
[loadOperation release];
}
}
}
}
編集: 本当に素晴らしい回答をありがとう。これが私の NSOperation コードと ThumbnailView コードです。週末にいくつかのことを試しましたが、スクロール中に操作キューを一時停止し、スクロールが終了したら再開することによってのみ、パフォーマンスを向上させることができました。
ここに私のコードスニペットがあります:
//In the init method
queue = [[NSOperationQueue alloc] init];
[queue setMaxConcurrentOperationCount:4];
//In the thumbnail view the loadImage and unloadImage methods
- (void) loadImage{
if(!loaded){
NSString *filename = [NSString stringWithFormat:@"%03d-cover-front", recipe.identifier, recipe.identifier];
NSString *directory = [NSString stringWithFormat:@"RestaurantContent/%03d", recipe.identifier];
NSString *path = [[NSBundle mainBundle] pathForResource:filename ofType:@"png" inDirectory:directory];
UIImage *image = [UIImage imageWithContentsOfFile:path];
imageView = [[ImageView alloc] initWithImage:image andFrame:CGRectMake(0.0f, 0.0f, 176.0f, 262.0f)];
[self addSubview:imageView];
[self sendSubviewToBack:imageView];
[imageView release];
loaded = YES;
}
}
- (void) unloadImage{
if(loaded){
[imageView removeFromSuperview];
imageView = nil;
loaded = NO;
}
}
次に、私のロードおよびアンロード操作:
- (id) initWithOperableImage:(id<OperableImage>) anOperableImage{
self = [super init];
if (self != nil) {
self.image = anOperableImage;
}
return self;
}
//This is the main method in the load image operation
- (void)main {
[image loadImage];
}
//This is the main method in the unload image operation
- (void)main {
[image unloadImage];
}