我有一个 UITableView
,它使用 GCD 将图像从 URL 异步加载到单元格中。问题是,如果用户轻拂超过 150 行,则有 150 个操作排队并执行。我想要的是出队/取消那些过去并离开屏幕的。
我该怎么做?
此时我的代码(相当标准):
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
// after getting the cell...
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
if (runQ) {
NSString *galleryTinyImageUrl = [[self.smapi getImageUrls:imageId imageKey:imageKey] objectForKey:@"TinyURL"];
NSData *imageData = [[NSData alloc] initWithContentsOfURL:[NSURL URLWithString:galleryTinyImageUrl]];
dispatch_async(dispatch_get_main_queue(), ^{
if (imageData != nil) {
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
cell.imageView.image = [UIImage imageWithData:imageData];
}
});
}
});
runQ 是一个 BOOL
ivar,我在 viewWillDisappear
上设置为 NO
,(我认为)它具有快速清除队列的效果当此 UITableView
从导航 Controller 弹出时。
那么,回到我最初的问题:如何取消对已离开屏幕的单元格的图像获取操作?谢谢。
最佳答案
首先,不要在滚动时排队操作。相反,仅在 viewDidLoad
和用户停止滚动时为可见行加载图像:
-(void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
for (NSIndexPath *indexPath in [self.tableView indexPathsForVisibleRows]) {
[self loadImageForCellAtPath:indexPath];
}
}
如果您仍然希望能够取消对不可见单元格的加载,您可以使用 NSBlockOperation
而不是 GCD:
self.operationQueue = [[[NSOperationQueue alloc] init] autorelease];
[self.operationQueue setMaxConcurrentOperationCount:NSOperationQueueDefaultMaxConcurrentOperationCount];
// ...
-(void)loadImageForCellAtPath:(NSIndexPath *)indexPath {
__block NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^{
if (![operation isCancelled]) {
NSString *galleryTinyImageUrl = [[self.smapi getImageUrls:imageId imageKey:imageKey] objectForKey:@"TinyURL"];
NSData *imageData = [[NSData alloc] initWithContentsOfURL:[NSURL URLWithString:galleryTinyImageUrl]];
dispatch_async(dispatch_get_main_queue(), ^{
if (imageData != nil) {
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
cell.imageView.image = [UIImage imageWithData:imageData];
}
});
}
}];
NSValue *nonRetainedOperation = [NSValue valueWithNonretainedObjectValue:operation];
[self.operations addObject:nonRetainedOperation forKey:indexPath];
[self.operationQueue addOperation:operation];
}
这里的 operations
是一个 NSMutableDictionary
。当你想取消一个操作时,你可以通过单元格的 indexPath
检索它,取消它,并将它从字典中删除:
NSValue *operationHolder = [self.operations objectForKey:indexPath];
NSOperation *operation = [operationHolder nonretainedObjectValue];
[operation cancel];
关于iphone - 在 UITableView 中,取消屏幕外单元格的 GCD 操作的最佳方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10408611/