问题是我管理滚动视图,里面有很多图块。每个可见的平铺显示从 URL 加载的图像或(在第一个 URL 加载后)在后台缓存的文件。不可见的瓷砖回收(设置新框架并重绘)。
图像负载取决于平铺位置。
对于长距离滚动,每个图块都会调用多次重绘:每个图块会多次加载(并显示)不同的图像,然后再显示正确的图像。
所以问题是在添加新之前取消所有先前添加的瓦片操作。
我将 NSInvocationOperation 子类化只是为了包含上下文对象以检测附加到的操作以及在添加新操作之前我取消同一个图块的所有操作:
-(void)loadWithColler:(TileView *)coller {
if (queue == nil) {
queue = [NSOperationQueue new];
}
NSInvocationOperationWithContext *loadImageOp = [NSInvocationOperationWithContext alloc];
[loadImageOp initWithTarget:self selector:@selector(loadImage:) object:loadImageOp];
[loadImageOp setContext:coller];
[queue setSuspended:YES];
NSArray *opers = [queue operations];
for (NSInvocationOperationWithContext *nextOperation in opers) {
if ([nextOperation context] == coller) {
[nextOperation cancel];
}
}
[queue addOperation:loadImageOp];
[queue setSuspended:NO];
[loadImageOp release];
}
在操作本身中,我检查 isCancelled:
-(void)loadImage:(NSInvocationOperationWithContext *)operation {
if (operation.isCancelled) return;
TileView *coller = [operation context];
/* TRY TO GET FILE FROM CACHE */
if (operation.isCancelled) return;
if (data) {
/* INIT WITH DATA IF LOADED */
} else {
/* LOAD FILE FROM URL AND CACHE IT */
}
if (operation.isCancelled) return;
NSInvocationOperation *setImageOp = [[NSInvocationOperation alloc] initWithTarget:coller selector:@selector(setImage:) object:cachedImage];
[[NSOperationQueue mainQueue] addOperation:setImageOp];
[setImageOp release];
}
但它是什么都不做。有时提前返回有效,但图块仍会在正确的图像之前加载许多图像。
那我怎么可能成功?滚动时,这么多不需要的操作会导致主线程延迟吗?(因为存在延迟,我不知道为什么......全部在后台加载......)
更新:
使用 NSLog: isCancelled while execution: > 取消 loadImage 方法: >
于是取消工作。
现在我保存对 TileView 对象中最后一个操作的引用,并且仅当调用的操作等于 TileView 操作时才执行 setImage 操作。
没什么区别...
看起来有很多操作将不同的图像加载到一个又一个调用的图块。
还有什么建议吗?
清关:
有单例 DataLoader (来自它的所有代码)。并且所有图块都在 drowRect 中调用它:
[[DataLoader sharedDataLoader] loadWithColler:self];
更新:
NSInvocationOperation 子类:
@interface NSInvocationOperationWithContext : NSInvocationOperation {
id context;
}
@property (nonatomic,retain,readwrite) id context;
@end
@implementation NSInvocationOperationWithContext
@synthesize context;
- (void)dealloc
{
[context release];
[super dealloc];
}
@end
非常感谢您的帮助!
解决方案:
从下面的答案:需要从 NSOperation 子类化
当我将 NSOperation 子类化并将所有 loadImage: 代码放入“main”方法时(只需将所有代码移至此处,仅此而已),一切都完美无缺!
至于滚动延迟:它会导致将图像加载到 UIImageView (由于解压缩和光栅化需要很长时间(据我了解)。
所以更好的方法是使用CATiledLayer。它在后台加载数据并且速度更快。